Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity.Design / System / Data / EntityModel / Emitters / TypeReference.cs
1 //---------------------------------------------------------------------
2 // <copyright file="TypeReference.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.CodeDom;
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;
17
18 namespace System.Data.EntityModel.Emitters
19 {
20     /// <summary>
21     /// Summary description for TypeReferences.
22     /// </summary>
23     internal class TypeReference
24     {
25         #region Fields
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";
32
33         public const string FQMetaDataWorkspaceTypeName = "System.Data.Metadata.Edm.MetadataWorkspace";
34
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;
46         #endregion
47
48         #region Constructors
49         internal TypeReference()
50         {
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);
55         }
56         #endregion
57
58         #region Public Methods
59         /// <summary>
60         /// Get the cached CodeTypeReference for a type represented by a Type object
61         /// </summary>
62         /// <param name="type">the type object</param>
63         /// <returns>the associated TypeReference object</returns>
64         public CodeTypeReference ForType(Type type)
65         {
66             return _forTypeMemoizer.Evaluate(type);
67         }
68
69         private CodeTypeReference ComputeForType(Type type)
70         {
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);
74             return value;
75         }
76
77         /// <summary>
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.
82         /// </summary>
83         /// <param name="type">the generic type object</param>
84         /// <returns>the associated TypeReference object</returns>
85         public CodeTypeReference ForType(Type generic, CodeTypeReference argument)
86         {
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);
91             return typeRef;
92         }
93
94
95         /// <summary>
96         /// Get TypeReference for a type represented by a namespace quailifed string 
97         /// </summary>
98         /// <param name="type">namespace qualified string</param>
99         /// <returns>the TypeReference</returns>
100         public CodeTypeReference FromString(string type)
101         {
102             return FromString(type, false);
103         }
104
105         /// <summary>
106         /// Get TypeReference for a type represented by a namespace quailifed string,
107         /// with optional global qualifier
108         /// </summary>
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)
113         {
114             return _fromStringMemoizer.Evaluate(new KeyValuePair<string, bool>(type, addGlobalQualifier));
115         }
116
117         private CodeTypeReference ComputeFromString(KeyValuePair<string, bool> arguments)
118         {
119             string type = arguments.Key;
120             bool addGlobalQualifier = arguments.Value;
121             CodeTypeReference value;
122             if (addGlobalQualifier)
123             {
124                 value = new CodeTypeReference(type, CodeTypeReferenceOptions.GlobalReference);
125             }
126             else
127             {
128                 value = new CodeTypeReference(type);
129             }
130             return value;
131         }
132
133         /// <summary>
134         /// Get TypeReference for a framework type
135         /// </summary>
136         /// <param name="name">unqualified name of the framework type</param>
137         /// <returns>the TypeReference</returns>
138         public CodeTypeReference AdoFrameworkType(string name)
139         {
140             return FromString(Utils.FQAdoFrameworkName(name), true);
141         }
142
143         /// <summary>
144         /// Get TypeReference for a framework DataClasses type
145         /// </summary>
146         /// <param name="name">unqualified name of the framework DataClass type</param>
147         /// <returns>the TypeReference</returns>
148         public CodeTypeReference AdoFrameworkDataClassesType(string name)
149         {
150             return FromString(Utils.FQAdoFrameworkDataClassesName(name), true);
151         }
152
153         /// <summary>
154         /// Get TypeReference for a framework Metadata Edm type
155         /// </summary>
156         /// <param name="name">unqualified name of the framework metadata edm type</param>
157         /// <returns>the TypeReference</returns>
158         public CodeTypeReference AdoFrameworkMetadataEdmType(string name)
159         {
160             return FromString(Utils.FQAdoFrameworkMetadataEdmName(name), true);
161         }
162
163         /// <summary>
164         /// Get TypeReference for a framework Entity Client type
165         /// </summary>
166         /// <param name="name">unqualified name of the framework type</param>
167         /// <returns>the TypeReference</returns>
168         public CodeTypeReference AdoEntityClientType(string name)
169         {
170             return FromString(Utils.FQAdoEntityClientName(name), true);
171         }
172
173         /// <summary>
174         /// Get TypeReference for a bound generic framework class
175         /// </summary>
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)
180         {
181             return FrameworkGenericClass(Utils.AdoFrameworkNamespace, name, typeParameter);
182         }
183         /// <summary>
184         /// Get TypeReference for a bound generic framework data class
185         /// </summary>
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)
190         {
191             return FrameworkGenericClass(Utils.AdoFrameworkDataClassesNamespace, name, typeParameter);
192         }
193
194         /// <summary>
195         /// Get TypeReference for a bound generic framework class
196         /// </summary>
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)
202         {
203             return _fromStringGenericMemoizer.Evaluate(new KeyValuePair<string, CodeTypeReference>(namespaceName + "." + name, typeParameter));
204         }
205
206         private CodeTypeReference ComputeFromStringGeneric(KeyValuePair<string, CodeTypeReference> arguments)
207         {
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);
212             return typeRef;
213         }
214
215         /// <summary>
216         /// Get TypeReference for a bound Nullable&lt;T&gt;
217         /// </summary>
218         /// <param name="innerType">Type of the Nullable&lt;T&gt; type parameter</param>
219         /// <returns>TypeReference for a bound Nullable&lt;T&gt;</returns>
220         public CodeTypeReference NullableForType(Type innerType)
221         {
222             return _nullableForTypeMemoizer.Evaluate(innerType);
223         }
224
225         private CodeTypeReference ComputeNullableForType(Type innerType)
226         {
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));
231             return typeRef;
232         }
233
234         /// <summary>
235         /// Gets an ObjectResult of elementType CodeTypeReference. 
236         /// </summary>
237         public CodeTypeReference ObjectResult(CodeTypeReference elementType)
238         {
239             return AdoFrameworkGenericClass(ObjectResultClassName, elementType);
240         }
241
242         #endregion
243
244         #region Public Properties
245         /// <summary>
246         /// Gets a CodeTypeReference to the System.Byte[] type.
247         /// </summary>
248         /// <value></value>
249         public CodeTypeReference ByteArray
250         {
251             get
252             {
253                 if (_byteArray == null)
254                 {
255                     _byteArray = ForType(typeof(byte[]));
256                 }
257
258                 return _byteArray;
259             }
260         }
261
262         /// <summary>
263         /// Gets a CodeTypeReference object for the System.DateTime type.
264         /// </summary>
265         public CodeTypeReference DateTime
266         {
267             get
268             {
269                 if (_dateTime == null)
270                 {
271                     _dateTime = ForType(typeof(System.DateTime));
272                 }
273
274                 return _dateTime;
275             }
276         }
277
278         /// <summary>
279         /// Gets a CodeTypeReference object for the System.DateTimeOffset type.
280         /// </summary>
281         public CodeTypeReference DateTimeOffset
282         {
283             get
284             {
285                 if (_dateTimeOffset == null)
286                 {
287                     _dateTimeOffset = ForType(typeof(System.DateTimeOffset));
288                 }
289
290                 return _dateTimeOffset;
291             }
292         }
293
294         /// <summary>
295         /// Gets a CodeTypeReference object for the System.Guid type.
296         /// </summary>
297         public CodeTypeReference Guid
298         {
299             get
300             {
301                 if (_guid == null)
302                 {
303                     _guid = ForType(typeof(System.Guid));
304                 }
305
306                 return _guid;
307             }
308         }
309
310         /// <summary>
311         /// TypeReference for the Framework's ObjectContext class
312         /// </summary>
313         public CodeTypeReference ObjectContext
314         {
315             get
316             {
317                 if (_objectContext == null)
318                 {
319                     _objectContext = AdoFrameworkType(NewContextClassName);
320                 }
321
322                 return _objectContext;
323             }
324         }
325
326         /// <summary>
327         /// TypeReference for the Framework base class to types that can used in InlineObjectCollection
328         /// </summary>
329         public CodeTypeReference ComplexTypeBaseClass
330         {
331             get
332             {
333                 return ForType(ComplexTypeBaseClassType);
334             }
335         }
336
337
338         /// <summary>
339         /// TypeReference for the Framework base class for EntityTypes
340         /// </summary>
341         public CodeTypeReference EntityTypeBaseClass
342         {
343             get
344             {
345                 return ForType(EntityTypeBaseClassType);
346             }
347         }
348
349         /// <summary>
350         /// TypeReference for the Framework base class for IEntityWithRelationships
351         /// </summary>
352         public CodeTypeReference IEntityWithRelationshipsTypeBaseClass
353         {
354             get
355             {
356                 return AdoFrameworkDataClassesType(IEntityWithRelationshipsTypeBaseClassName);
357             }
358         }
359
360         /// <summary>
361         /// Gets a CodeTypeReference object for the System.String type.
362         /// </summary>
363         public CodeTypeReference String
364         {
365             get
366             {
367                 if (_string == null)
368                 {
369                     _string = ForType(typeof(string));
370                 }
371                 return _string;
372             }
373         }
374
375         /// <summary>
376         /// Gets a CodeTypeReference object for the System.TimeSpan type.
377         /// </summary>
378         public CodeTypeReference TimeSpan
379         {
380             get
381             {
382                 if (_timeSpan == null)
383                 {
384                     _timeSpan = ForType(typeof(System.TimeSpan));
385                 }
386                 return _timeSpan;
387             }
388         }
389         #endregion
390
391     }
392 }