1 /* Copyright (C) 2007   Versant Inc.   http://www.db4o.com */
2 using System;
3 
4 namespace Db4objects.Db4o.Reflect.Net
5 {
6     public class NetArray : Db4objects.Db4o.Reflect.Core.AbstractReflectArray
7     {
NetArray(IReflector reflector)8         public NetArray(IReflector reflector) : base(reflector)
9         {
10         }
11 
GetNetType(IReflectClass clazz)12         private static Type GetNetType(IReflectClass clazz)
13 		{
14 			return ((NetClass)clazz).GetNetType();
15 		}
16 
Analyze(object obj, ArrayInfo info)17         public override void Analyze(object obj, ArrayInfo info)
18         {
19             info.Nullable(IsNullableType(obj.GetType()));
20         }
21 
IsNullableType(Type type)22         private bool IsNullableType(Type type)
23         {
24             if (type.IsArray)
25             {
26                 return IsNullableType(type.GetElementType());
27             }
28 
29             Type underlyingType = Nullable.GetUnderlyingType(type);
30             return underlyingType != null;
31         }
32 
NewInstance(IReflectClass componentType, ArrayInfo info)33         public override object NewInstance(IReflectClass componentType, ArrayInfo info)
34         {
35             Type type = GetNetType(componentType);
36             if (info.Nullable())
37             {
38                 type = NullableType(type);
39             }
40             MultidimensionalArrayInfo multiDimensionalInfo = info as MultidimensionalArrayInfo;
41             if (multiDimensionalInfo == null)
42             {
43                 return System.Array.CreateInstance(type, info.ElementCount());
44             }
45             int[] dimensions = multiDimensionalInfo.Dimensions();
46             if (dimensions.Length == 1)
47             {
48                 return UnfoldArrayCreation(type, dimensions, 0);
49             }
50             return UnfoldArrayCreation(GetArrayType(type, dimensions.Length - 1), dimensions, 0);
51         }
52 
NullableType(Type type)53         private Type NullableType(Type type)
54         {
55             if(IsNullableType(type))
56             {
57                 return type;
58             }
59             return typeof(Nullable<>).MakeGenericType(new Type[] { type });
60         }
61 
NewInstance(IReflectClass componentType, int[] dimensions)62         public override object NewInstance(IReflectClass componentType, int[] dimensions)
63         {
64             Type type = GetNetType(componentType);
65             if (dimensions.Length == 1)
66             {
67                 return UnfoldArrayCreation(type, dimensions, 0);
68             }
69 
70             return UnfoldArrayCreation(GetArrayType(type, dimensions.Length - 1), dimensions, 0);
71         }
72 
UnfoldArrayCreation(Type type, int[] dimensions, int dimensionIndex)73         private static object UnfoldArrayCreation(Type type, int[] dimensions, int dimensionIndex)
74         {
75             int length = dimensions[dimensionIndex];
76             Array array = Array.CreateInstance(type, length);
77             if (dimensionIndex == dimensions.Length - 1)
78             {
79                 return array;
80             }
81             for (int i=0; i<length; ++i)
82             {
83                 object value = UnfoldArrayCreation(type.GetElementType(), dimensions, dimensionIndex + 1);
84                 array.SetValue(value, i);
85             }
86             return array;
87         }
88 
GetArrayType(Type type, int dimensions)89         private static System.Type GetArrayType(Type type, int dimensions)
90         {
91 			if (dimensions < 1) throw new ArgumentOutOfRangeException("dimensions");
92 
93             Type arrayType = MakeArrayType(type);
94             for (int i=1; i<dimensions; ++i)
95             {
96                 arrayType = MakeArrayType(arrayType);
97             }
98             return arrayType;
99         }
100 
MakeArrayType(Type type)101         private static Type MakeArrayType(Type type)
102         {
103         	return Sharpen.Lang.ArrayTypeReference.MakeArrayType(type, 1);
104         }
105 
NewInstance(IReflectClass componentType, int length)106         public override object NewInstance(IReflectClass componentType, int length)
107         {
108             return System.Array.CreateInstance(GetNetType(componentType), length);
109         }
110     }
111 }
112