1 //---------------------------------------------------------------------
2 // <copyright file="TypeReference.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
12 using System.Collections;
13 using System.Collections.Generic;
14 using System.Data.EntityModel.SchemaObjectModel;
15 using System.Data.Common.Utils;
16 using System.Reflection;
18 namespace System.Data.EntityModel.Emitters
21 /// Summary description for TypeReferences.
23 internal class TypeReference
26 internal static readonly Type ComplexTypeBaseClassType = typeof(System.Data.Objects.DataClasses.ComplexObject);
27 internal static readonly Type EntityTypeBaseClassType = typeof(System.Data.Objects.DataClasses.EntityObject);
28 private const string IEntityWithRelationshipsTypeBaseClassName = "IEntityWithRelationships";
29 private const string NewContextClassName = "ObjectContext";
30 private const string EntitySetClassName = "EntitySet";
31 private const string ObjectResultClassName = "ObjectResult";
33 public const string FQMetaDataWorkspaceTypeName = "System.Data.Metadata.Edm.MetadataWorkspace";
35 private static CodeTypeReference _byteArray;
36 private static CodeTypeReference _dateTime;
37 private static CodeTypeReference _dateTimeOffset;
38 private static CodeTypeReference _guid;
39 private static CodeTypeReference _objectContext;
40 private static CodeTypeReference _string;
41 private static CodeTypeReference _timeSpan;
42 private readonly Memoizer<Type, CodeTypeReference> _forTypeMemoizer;
43 private readonly Memoizer<Type, CodeTypeReference> _nullableForTypeMemoizer;
44 private readonly Memoizer<KeyValuePair<string, bool>, CodeTypeReference> _fromStringMemoizer;
45 private readonly Memoizer<KeyValuePair<string, CodeTypeReference>, CodeTypeReference> _fromStringGenericMemoizer;
49 internal TypeReference()
51 _forTypeMemoizer = new Memoizer<Type, CodeTypeReference>(ComputeForType, null);
52 _fromStringMemoizer = new Memoizer<KeyValuePair<string, bool>, CodeTypeReference>(ComputeFromString, null);
53 _nullableForTypeMemoizer = new Memoizer<Type, CodeTypeReference>(ComputeNullableForType, null);
54 _fromStringGenericMemoizer = new Memoizer<KeyValuePair<string, CodeTypeReference>, CodeTypeReference>(ComputeFromStringGeneric, null);
58 #region Public Methods
60 /// Get the cached CodeTypeReference for a type represented by a Type object
62 /// <param name="type">the type object</param>
63 /// <returns>the associated TypeReference object</returns>
64 public CodeTypeReference ForType(Type type)
66 return _forTypeMemoizer.Evaluate(type);
69 private CodeTypeReference ComputeForType(Type type)
71 // we know that we can safely global:: qualify this because it was already
72 // compiled before we are emitting or else we wouldn't have a Type object
73 CodeTypeReference value = new CodeTypeReference(type, CodeTypeReferenceOptions.GlobalReference);
78 /// Get TypeReference for a type represented by a Generic Type object.
79 /// We don't cache the TypeReference for generic type object since the type would be the same
80 /// irresepective of the generic arguments. We could potentially cache it using both the type name
81 /// and generic type arguments.
83 /// <param name="type">the generic type object</param>
84 /// <returns>the associated TypeReference object</returns>
85 public CodeTypeReference ForType(Type generic, CodeTypeReference argument)
87 // we know that we can safely global:: qualify this because it was already
88 // compiled before we are emitting or else we wouldn't have a Type object
89 CodeTypeReference typeRef = new CodeTypeReference(generic, CodeTypeReferenceOptions.GlobalReference);
90 typeRef.TypeArguments.Add(argument);
96 /// Get TypeReference for a type represented by a namespace quailifed string
98 /// <param name="type">namespace qualified string</param>
99 /// <returns>the TypeReference</returns>
100 public CodeTypeReference FromString(string type)
102 return FromString(type, false);
106 /// Get TypeReference for a type represented by a namespace quailifed string,
107 /// with optional global qualifier
109 /// <param name="type">namespace qualified string</param>
110 /// <param name="addGlobalQualifier">indicates whether the global qualifier should be added</param>
111 /// <returns>the TypeReference</returns>
112 public CodeTypeReference FromString(string type, bool addGlobalQualifier)
114 return _fromStringMemoizer.Evaluate(new KeyValuePair<string, bool>(type, addGlobalQualifier));
117 private CodeTypeReference ComputeFromString(KeyValuePair<string, bool> arguments)
119 string type = arguments.Key;
120 bool addGlobalQualifier = arguments.Value;
121 CodeTypeReference value;
122 if (addGlobalQualifier)
124 value = new CodeTypeReference(type, CodeTypeReferenceOptions.GlobalReference);
128 value = new CodeTypeReference(type);
134 /// Get TypeReference for a framework type
136 /// <param name="name">unqualified name of the framework type</param>
137 /// <returns>the TypeReference</returns>
138 public CodeTypeReference AdoFrameworkType(string name)
140 return FromString(Utils.FQAdoFrameworkName(name), true);
144 /// Get TypeReference for a framework DataClasses type
146 /// <param name="name">unqualified name of the framework DataClass type</param>
147 /// <returns>the TypeReference</returns>
148 public CodeTypeReference AdoFrameworkDataClassesType(string name)
150 return FromString(Utils.FQAdoFrameworkDataClassesName(name), true);
154 /// Get TypeReference for a framework Metadata Edm type
156 /// <param name="name">unqualified name of the framework metadata edm type</param>
157 /// <returns>the TypeReference</returns>
158 public CodeTypeReference AdoFrameworkMetadataEdmType(string name)
160 return FromString(Utils.FQAdoFrameworkMetadataEdmName(name), true);
164 /// Get TypeReference for a framework Entity Client type
166 /// <param name="name">unqualified name of the framework type</param>
167 /// <returns>the TypeReference</returns>
168 public CodeTypeReference AdoEntityClientType(string name)
170 return FromString(Utils.FQAdoEntityClientName(name), true);
174 /// Get TypeReference for a bound generic framework class
176 /// <param name="name">the name of the generic framework class</param>
177 /// <param name="typeParameter">the type parameter for the framework class</param>
178 /// <returns>TypeReference for the bound framework class</returns>
179 public CodeTypeReference AdoFrameworkGenericClass(string name, CodeTypeReference typeParameter)
181 return FrameworkGenericClass(Utils.AdoFrameworkNamespace, name, typeParameter);
184 /// Get TypeReference for a bound generic framework data class
186 /// <param name="name">the name of the generic framework data class</param>
187 /// <param name="typeParameter">the type parameter for the framework data class</param>
188 /// <returns>TypeReference for the bound framework data class</returns>
189 public CodeTypeReference AdoFrameworkGenericDataClass(string name, CodeTypeReference typeParameter)
191 return FrameworkGenericClass(Utils.AdoFrameworkDataClassesNamespace, name, typeParameter);
195 /// Get TypeReference for a bound generic framework class
197 /// <param name="namespaceName">the namespace of the generic framework class</param>
198 /// <param name="name">the name of the generic framework class</param>
199 /// <param name="typeParameter">the type parameter for the framework class</param>
200 /// <returns>TypeReference for the bound framework class</returns>
201 private CodeTypeReference FrameworkGenericClass(string namespaceName, string name, CodeTypeReference typeParameter)
203 return _fromStringGenericMemoizer.Evaluate(new KeyValuePair<string, CodeTypeReference>(namespaceName + "." + name, typeParameter));
206 private CodeTypeReference ComputeFromStringGeneric(KeyValuePair<string, CodeTypeReference> arguments)
208 string name = arguments.Key;
209 CodeTypeReference typeParameter = arguments.Value;
210 CodeTypeReference typeRef = ComputeFromString(new KeyValuePair<string, bool>(name, true));
211 typeRef.TypeArguments.Add(typeParameter);
216 /// Get TypeReference for a bound Nullable<T>
218 /// <param name="innerType">Type of the Nullable<T> type parameter</param>
219 /// <returns>TypeReference for a bound Nullable<T></returns>
220 public CodeTypeReference NullableForType(Type innerType)
222 return _nullableForTypeMemoizer.Evaluate(innerType);
225 private CodeTypeReference ComputeNullableForType(Type innerType)
227 // can't use FromString because it will return the same Generic type reference
228 // but it will already have a previous type parameter (because of caching)
229 CodeTypeReference typeRef = new CodeTypeReference(typeof(System.Nullable<>), CodeTypeReferenceOptions.GlobalReference);
230 typeRef.TypeArguments.Add(ForType(innerType));
235 /// Gets an ObjectResult of elementType CodeTypeReference.
237 public CodeTypeReference ObjectResult(CodeTypeReference elementType)
239 return AdoFrameworkGenericClass(ObjectResultClassName, elementType);
244 #region Public Properties
246 /// Gets a CodeTypeReference to the System.Byte[] type.
249 public CodeTypeReference ByteArray
253 if (_byteArray == null)
255 _byteArray = ForType(typeof(byte[]));
263 /// Gets a CodeTypeReference object for the System.DateTime type.
265 public CodeTypeReference DateTime
269 if (_dateTime == null)
271 _dateTime = ForType(typeof(System.DateTime));
279 /// Gets a CodeTypeReference object for the System.DateTimeOffset type.
281 public CodeTypeReference DateTimeOffset
285 if (_dateTimeOffset == null)
287 _dateTimeOffset = ForType(typeof(System.DateTimeOffset));
290 return _dateTimeOffset;
295 /// Gets a CodeTypeReference object for the System.Guid type.
297 public CodeTypeReference Guid
303 _guid = ForType(typeof(System.Guid));
311 /// TypeReference for the Framework's ObjectContext class
313 public CodeTypeReference ObjectContext
317 if (_objectContext == null)
319 _objectContext = AdoFrameworkType(NewContextClassName);
322 return _objectContext;
327 /// TypeReference for the Framework base class to types that can used in InlineObjectCollection
329 public CodeTypeReference ComplexTypeBaseClass
333 return ForType(ComplexTypeBaseClassType);
339 /// TypeReference for the Framework base class for EntityTypes
341 public CodeTypeReference EntityTypeBaseClass
345 return ForType(EntityTypeBaseClassType);
350 /// TypeReference for the Framework base class for IEntityWithRelationships
352 public CodeTypeReference IEntityWithRelationshipsTypeBaseClass
356 return AdoFrameworkDataClassesType(IEntityWithRelationshipsTypeBaseClassName);
361 /// Gets a CodeTypeReference object for the System.String type.
363 public CodeTypeReference String
369 _string = ForType(typeof(string));
376 /// Gets a CodeTypeReference object for the System.TimeSpan type.
378 public CodeTypeReference TimeSpan
382 if (_timeSpan == null)
384 _timeSpan = ForType(typeof(System.TimeSpan));