Kinetica   C#   API  Version 7.2.3.0
ObjectCreator.cs
Go to the documentation of this file.
1 
18 using System;
19 using System.Collections.Generic;
20 using System.Text;
21 using System.Reflection;
22 using System.Reflection.Emit;
23 
24 namespace Avro.Specific
25 {
26 
27  public sealed class ObjectCreator
28  {
29  private static readonly ObjectCreator instance = new ObjectCreator();
30  public static ObjectCreator Instance { get { return instance; } }
31 
35  private Type GenericMapType = typeof(Dictionary<,>);
36 
40  private Type GenericListType = typeof(List<>);
41 
45  private Type GenericNullableType = typeof(Nullable<>);
46 
47  private readonly Assembly execAssembly;
48  private readonly Assembly entryAssembly;
49  private readonly bool diffAssembly;
50 
51  public delegate object CtorDelegate();
52  private Type ctorType = typeof(CtorDelegate);
53  Dictionary<NameCtorKey, CtorDelegate> ctors;
54 
55  private ObjectCreator()
56  {
57  execAssembly = System.Reflection.Assembly.GetExecutingAssembly();
58  entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
59  if (entryAssembly != null && execAssembly != entryAssembly) // entryAssembly returns null when running from NUnit
60  diffAssembly = true;
61 
62  GenericMapType = typeof(Dictionary<,>);
63  GenericListType = typeof(List<>);
64 
65  ctors = new Dictionary<NameCtorKey, CtorDelegate>();
66  }
67 
68  public struct NameCtorKey : IEquatable<NameCtorKey>
69  {
70  public string name { get; private set; }
71  public Schema.Type type { get; private set; }
72  public NameCtorKey(string value1, Schema.Type value2)
73  : this()
74  {
75  name = value1;
76  type = value2;
77  }
78  public bool Equals(NameCtorKey other)
79  {
80  return Equals(other.name, name) && other.type == type;
81  }
82  public override bool Equals(object obj)
83  {
84  if (ReferenceEquals(null, obj))
85  return false;
86  if (obj.GetType() != typeof(NameCtorKey))
87  return false;
88  return Equals((NameCtorKey)obj);
89  }
90  public override int GetHashCode()
91  {
92  unchecked
93  {
94  return ((name != null ? name.GetHashCode() : 0) * 397) ^ type.GetHashCode();
95  }
96  }
97  public static bool operator ==(NameCtorKey left, NameCtorKey right)
98  {
99  return left.Equals(right);
100  }
101  public static bool operator !=(NameCtorKey left, NameCtorKey right)
102  {
103  return !left.Equals(right);
104  }
105  }
106 
113  private Type FindType(string name,bool throwError)
114  {
115  Type type;
116 
117  // Modify provided type to ensure it can be discovered.
118  // This is mainly for Generics, and Nullables.
119  name = name.Replace("Nullable", "Nullable`1");
120  name = name.Replace("IList<", "System.Collections.Generic.IList`1[");
121  name = name.Replace("IDictionary<string,", "System.Collections.Generic.IDictionary`2[System.String,");
122  name = name.Replace("IDictionary<", "System.Collections.Generic.IDictionary`2[");
123  name = name.Replace("<", "[");
124  name = name.Replace(">", "]");
125 
126  if (diffAssembly)
127  {
128  // entry assembly different from current assembly, try entry assembly first
129  type = entryAssembly.GetType(name);
130  if (type == null) // now try current assembly and mscorlib
131  type = Type.GetType(name);
132  }
133  else
134  type = Type.GetType(name);
135 
136  Type[] types;
137 
138  if (type == null) // type is still not found, need to loop through all loaded assemblies
139  {
140  Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
141  foreach (Assembly assembly in assemblies)
142  {
143  // Fix for Mono 3.0.10
144  if (assembly.FullName.StartsWith("MonoDevelop.NUnit"))
145  continue;
146 
147  types = assembly.GetTypes();
148 
149  // Change the search to look for Types by both NAME and FULLNAME
150  foreach (Type t in types)
151  {
152  if (name == t.Name || name == t.FullName) type = t;
153  }
154 
155  if (type != null)
156  break;
157  }
158  }
159 
160  if (null == type && throwError)
161  {
162  throw new AvroException("Unable to find type " + name + " in all loaded assemblies");
163  }
164 
165  return type;
166  }
167 
168 
174  public Type GetType(Schema schema)
175  {
176  switch(schema.Tag) {
177  case Schema.Type.Null:
178  break;
179  case Schema.Type.Boolean:
180  return typeof(bool);
181  case Schema.Type.Int:
182  return typeof(int);
183  case Schema.Type.Long:
184  return typeof(long);
185  case Schema.Type.Float:
186  return typeof(float);
187  case Schema.Type.Double:
188  return typeof(double);
189  case Schema.Type.Bytes:
190  return typeof(byte[]);
191  case Schema.Type.String:
192  return typeof(string);
193  case Schema.Type.Union:
194  {
195  UnionSchema unSchema = schema as UnionSchema;
196  if (null != unSchema && unSchema.Count==2)
197  {
198  Schema s1 = unSchema.Schemas[0];
199  Schema s2 = unSchema.Schemas[1];
200 
201  // Nullable ?
202  Type itemType = null;
203  if (s1.Tag == Schema.Type.Null)
204  {
205  itemType = GetType(s2);
206  }
207  else if (s2.Tag == Schema.Type.Null)
208  {
209  itemType = GetType(s1);
210  }
211 
212  if (null != itemType )
213  {
214  if (itemType.IsValueType && !itemType.IsEnum)
215  {
216  try
217  {
218  return GenericNullableType.MakeGenericType(new [] {itemType});
219  }
220  catch (Exception) { }
221  }
222 
223  return itemType;
224  }
225  }
226 
227  return typeof(object);
228  }
229  case Schema.Type.Array: {
230  ArraySchema arrSchema = schema as ArraySchema;
231  Type itemSchema = GetType(arrSchema.ItemSchema);
232 
233  return GenericListType.MakeGenericType(new [] {itemSchema}); }
234  case Schema.Type.Map: {
235  MapSchema mapSchema = schema as MapSchema;
236  Type itemSchema = GetType(mapSchema.ValueSchema);
237 
238  return GenericMapType.MakeGenericType(new [] { typeof(string), itemSchema }); }
239  case Schema.Type.Enumeration:
240  case Schema.Type.Record:
241  case Schema.Type.Fixed:
242  case Schema.Type.Error: {
243  // Should all be named types
244  var named = schema as NamedSchema;
245  if(null!=named) {
246  return FindType(named.Fullname,true);
247  }
248  break; }
249  }
250 
251  // Fallback
252  return FindType(schema.Name,true);
253  }
254 
261  public Type GetType(string name, Schema.Type schemaType)
262  {
263  Type type = FindType(name, true);
264 
265  if (schemaType == Schema.Type.Map)
266  {
267  type = GenericMapType.MakeGenericType(new[] { typeof(string), type });
268  }
269  else if (schemaType == Schema.Type.Array)
270  {
271  type = GenericListType.MakeGenericType(new [] {type});
272  }
273 
274  return type;
275  }
276 
284  public CtorDelegate GetConstructor(string name, Schema.Type schemaType, Type type)
285  {
286  ConstructorInfo ctorInfo = type.GetConstructor(Type.EmptyTypes);
287  if (ctorInfo == null)
288  throw new AvroException("Class " + name + " has no default constructor");
289 
290  DynamicMethod dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + name, typeof(object), null, type, true);
291  ILGenerator ilGen = dynMethod.GetILGenerator();
292  ilGen.Emit(OpCodes.Nop);
293  ilGen.Emit(OpCodes.Newobj, ctorInfo);
294  ilGen.Emit(OpCodes.Ret);
295 
296  return (CtorDelegate)dynMethod.CreateDelegate(ctorType);
297  }
298 
305  public object New(string name, Schema.Type schemaType)
306  {
307  NameCtorKey key = new NameCtorKey(name, schemaType);
308 
309  CtorDelegate ctor;
310  lock(ctors)
311  {
312  if (!ctors.TryGetValue(key, out ctor))
313  {
314  Type type = GetType(name, schemaType);
315  ctor = GetConstructor(name, schemaType, type);
316 
317  ctors.Add(key, ctor);
318  }
319  }
320  return ctor();
321  }
322  }
323 }
CtorDelegate GetConstructor(string name, Schema.Type schemaType, Type type)
Gets the default constructor for the specified type
static bool operator==(NameCtorKey left, NameCtorKey right)
override int GetHashCode()
Hash code function
Definition: Schema.cs:272
static bool operator !=(NameCtorKey left, NameCtorKey right)
Schema ValueSchema
Schema for map values type
Definition: MapSchema.cs:33
NameCtorKey(string value1, Schema.Type value2)
Base class for all schema types
Definition: Schema.cs:29
Class for union schemas
Definition: UnionSchema.cs:29
IList< Schema > Schemas
List of schemas in the union
Definition: UnionSchema.cs:34
Type
Enum for schema types
Definition: Schema.cs:34
delegate object CtorDelegate()
override bool Equals(object obj)
Class for array type schemas
Definition: ArraySchema.cs:27
Class for map schemas
Definition: MapSchema.cs:28
Type GetType(Schema schema)
Gets the type for the specified schema
object New(string name, Schema.Type schemaType)
Creates new instance of the given type
Type GetType(string name, Schema.Type schemaType)
Gets the type of the specified type name
static ObjectCreator Instance
abstract string Name
The name of this schema.
Definition: Schema.cs:77
int Count
Count of schemas in the union
Definition: UnionSchema.cs:39
Schema ItemSchema
Schema for the array 'type' attribute
Definition: ArraySchema.cs:32
Type Tag
Schema type property
Definition: Schema.cs:56
Base class for all named schemas: fixed, enum, record
Definition: NamedSchema.cs:29