1 |
b63dcfbb
|
semi
|
<#@ template language="C#" debug="false" hostspecific="true"#>
|
2 |
|
|
<#@ include file="EF6.Utility.CS.ttinclude"#><#@
|
3 |
|
|
output extension=".cs"#><#
|
4 |
|
|
|
5 |
|
|
const string inputFile = @"MarkusModel.edmx";
|
6 |
|
|
var textTransform = DynamicTextTransformation.Create(this);
|
7 |
|
|
var code = new CodeGenerationTools(this);
|
8 |
|
|
var ef = new MetadataTools(this);
|
9 |
|
|
var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
|
10 |
|
|
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
|
11 |
|
|
var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
|
12 |
|
|
var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
|
13 |
|
|
|
14 |
|
|
if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
|
15 |
|
|
{
|
16 |
|
|
return string.Empty;
|
17 |
|
|
}
|
18 |
|
|
|
19 |
|
|
WriteHeader(codeStringGenerator, fileManager);
|
20 |
|
|
|
21 |
|
|
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
|
22 |
|
|
{
|
23 |
|
|
fileManager.StartNewFile(entity.Name + ".cs");
|
24 |
|
|
BeginNamespace(code);
|
25 |
|
|
#>
|
26 |
|
|
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
|
27 |
|
|
<#=codeStringGenerator.EntityClassOpening(entity)#>
|
28 |
|
|
{
|
29 |
|
|
<#
|
30 |
|
|
var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
|
31 |
|
|
var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
|
32 |
|
|
var complexProperties = typeMapper.GetComplexProperties(entity);
|
33 |
|
|
|
34 |
|
|
if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
|
35 |
|
|
{
|
36 |
|
|
#>
|
37 |
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
|
38 |
|
|
public <#=code.Escape(entity)#>()
|
39 |
|
|
{
|
40 |
|
|
<#
|
41 |
|
|
foreach (var edmProperty in propertiesWithDefaultValues)
|
42 |
|
|
{
|
43 |
|
|
#>
|
44 |
|
|
this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
|
45 |
|
|
<#
|
46 |
|
|
}
|
47 |
|
|
|
48 |
|
|
foreach (var navigationProperty in collectionNavigationProperties)
|
49 |
|
|
{
|
50 |
|
|
#>
|
51 |
|
|
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
|
52 |
|
|
<#
|
53 |
|
|
}
|
54 |
|
|
|
55 |
|
|
foreach (var complexProperty in complexProperties)
|
56 |
|
|
{
|
57 |
|
|
#>
|
58 |
|
|
this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
|
59 |
|
|
<#
|
60 |
|
|
}
|
61 |
|
|
#>
|
62 |
|
|
}
|
63 |
|
|
|
64 |
|
|
<#
|
65 |
|
|
}
|
66 |
|
|
|
67 |
|
|
var simpleProperties = typeMapper.GetSimpleProperties(entity);
|
68 |
|
|
if (simpleProperties.Any())
|
69 |
|
|
{
|
70 |
|
|
foreach (var edmProperty in simpleProperties)
|
71 |
|
|
{
|
72 |
|
|
#>
|
73 |
|
|
<#=codeStringGenerator.Property(edmProperty)#>
|
74 |
|
|
<#
|
75 |
|
|
}
|
76 |
|
|
}
|
77 |
|
|
|
78 |
|
|
if (complexProperties.Any())
|
79 |
|
|
{
|
80 |
|
|
#>
|
81 |
|
|
|
82 |
|
|
<#
|
83 |
|
|
foreach(var complexProperty in complexProperties)
|
84 |
|
|
{
|
85 |
|
|
#>
|
86 |
|
|
<#=codeStringGenerator.Property(complexProperty)#>
|
87 |
|
|
<#
|
88 |
|
|
}
|
89 |
|
|
}
|
90 |
|
|
|
91 |
|
|
var navigationProperties = typeMapper.GetNavigationProperties(entity);
|
92 |
|
|
if (navigationProperties.Any())
|
93 |
|
|
{
|
94 |
|
|
#>
|
95 |
|
|
|
96 |
|
|
<#
|
97 |
|
|
foreach (var navigationProperty in navigationProperties)
|
98 |
|
|
{
|
99 |
|
|
if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
|
100 |
|
|
{
|
101 |
|
|
#>
|
102 |
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
|
103 |
|
|
<#
|
104 |
|
|
}
|
105 |
|
|
#>
|
106 |
|
|
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
|
107 |
|
|
<#
|
108 |
|
|
}
|
109 |
|
|
}
|
110 |
|
|
#>
|
111 |
|
|
}
|
112 |
|
|
<#
|
113 |
|
|
EndNamespace(code);
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
foreach (var complex in typeMapper.GetItemsToGenerate<ComplexType>(itemCollection))
|
117 |
|
|
{
|
118 |
|
|
fileManager.StartNewFile(complex.Name + ".cs");
|
119 |
|
|
BeginNamespace(code);
|
120 |
|
|
#>
|
121 |
|
|
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
|
122 |
|
|
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
|
123 |
|
|
{
|
124 |
|
|
<#
|
125 |
|
|
var complexProperties = typeMapper.GetComplexProperties(complex);
|
126 |
|
|
var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
|
127 |
|
|
|
128 |
|
|
if (propertiesWithDefaultValues.Any() || complexProperties.Any())
|
129 |
|
|
{
|
130 |
|
|
#>
|
131 |
|
|
public <#=code.Escape(complex)#>()
|
132 |
|
|
{
|
133 |
|
|
<#
|
134 |
|
|
foreach (var edmProperty in propertiesWithDefaultValues)
|
135 |
|
|
{
|
136 |
|
|
#>
|
137 |
|
|
this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
|
138 |
|
|
<#
|
139 |
|
|
}
|
140 |
|
|
|
141 |
|
|
foreach (var complexProperty in complexProperties)
|
142 |
|
|
{
|
143 |
|
|
#>
|
144 |
|
|
this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
|
145 |
|
|
<#
|
146 |
|
|
}
|
147 |
|
|
#>
|
148 |
|
|
}
|
149 |
|
|
|
150 |
|
|
<#
|
151 |
|
|
}
|
152 |
|
|
|
153 |
|
|
var simpleProperties = typeMapper.GetSimpleProperties(complex);
|
154 |
|
|
if (simpleProperties.Any())
|
155 |
|
|
{
|
156 |
|
|
foreach(var edmProperty in simpleProperties)
|
157 |
|
|
{
|
158 |
|
|
#>
|
159 |
|
|
<#=codeStringGenerator.Property(edmProperty)#>
|
160 |
|
|
<#
|
161 |
|
|
}
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
if (complexProperties.Any())
|
165 |
|
|
{
|
166 |
|
|
#>
|
167 |
|
|
|
168 |
|
|
<#
|
169 |
|
|
foreach(var edmProperty in complexProperties)
|
170 |
|
|
{
|
171 |
|
|
#>
|
172 |
|
|
<#=codeStringGenerator.Property(edmProperty)#>
|
173 |
|
|
<#
|
174 |
|
|
}
|
175 |
|
|
}
|
176 |
|
|
#>
|
177 |
|
|
}
|
178 |
|
|
<#
|
179 |
|
|
EndNamespace(code);
|
180 |
|
|
}
|
181 |
|
|
|
182 |
|
|
foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection))
|
183 |
|
|
{
|
184 |
|
|
fileManager.StartNewFile(enumType.Name + ".cs");
|
185 |
|
|
BeginNamespace(code);
|
186 |
|
|
#>
|
187 |
|
|
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
|
188 |
|
|
<#
|
189 |
|
|
if (typeMapper.EnumIsFlags(enumType))
|
190 |
|
|
{
|
191 |
|
|
#>
|
192 |
|
|
[Flags]
|
193 |
|
|
<#
|
194 |
|
|
}
|
195 |
|
|
#>
|
196 |
|
|
<#=codeStringGenerator.EnumOpening(enumType)#>
|
197 |
|
|
{
|
198 |
|
|
<#
|
199 |
|
|
var foundOne = false;
|
200 |
|
|
|
201 |
|
|
foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType))
|
202 |
|
|
{
|
203 |
|
|
foundOne = true;
|
204 |
|
|
#>
|
205 |
|
|
<#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>,
|
206 |
|
|
<#
|
207 |
|
|
}
|
208 |
|
|
|
209 |
|
|
if (foundOne)
|
210 |
|
|
{
|
211 |
|
|
this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1);
|
212 |
|
|
}
|
213 |
|
|
#>
|
214 |
|
|
}
|
215 |
|
|
<#
|
216 |
|
|
EndNamespace(code);
|
217 |
|
|
}
|
218 |
|
|
|
219 |
|
|
fileManager.Process();
|
220 |
|
|
|
221 |
|
|
#>
|
222 |
|
|
<#+
|
223 |
|
|
|
224 |
|
|
public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager)
|
225 |
|
|
{
|
226 |
|
|
fileManager.StartHeader();
|
227 |
|
|
#>
|
228 |
|
|
//------------------------------------------------------------------------------
|
229 |
|
|
// <auto-generated>
|
230 |
|
|
// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
|
231 |
|
|
//
|
232 |
|
|
// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
|
233 |
|
|
// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
|
234 |
|
|
// </auto-generated>
|
235 |
|
|
//------------------------------------------------------------------------------
|
236 |
|
|
<#=codeStringGenerator.UsingDirectives(inHeader: true)#>
|
237 |
|
|
<#+
|
238 |
|
|
fileManager.EndBlock();
|
239 |
|
|
}
|
240 |
|
|
|
241 |
|
|
public void BeginNamespace(CodeGenerationTools code)
|
242 |
|
|
{
|
243 |
|
|
var codeNamespace = code.VsNamespaceSuggestion();
|
244 |
|
|
if (!String.IsNullOrEmpty(codeNamespace))
|
245 |
|
|
{
|
246 |
|
|
#>
|
247 |
|
|
namespace <#=code.EscapeNamespace(codeNamespace)#>
|
248 |
|
|
{
|
249 |
|
|
<#+
|
250 |
|
|
PushIndent(" ");
|
251 |
|
|
}
|
252 |
|
|
}
|
253 |
|
|
|
254 |
|
|
public void EndNamespace(CodeGenerationTools code)
|
255 |
|
|
{
|
256 |
|
|
if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion()))
|
257 |
|
|
{
|
258 |
|
|
PopIndent();
|
259 |
|
|
#>
|
260 |
|
|
}
|
261 |
|
|
<#+
|
262 |
|
|
}
|
263 |
|
|
}
|
264 |
|
|
|
265 |
|
|
public const string TemplateId = "CSharp_DbContext_Types_EF6";
|
266 |
|
|
|
267 |
|
|
public class CodeStringGenerator
|
268 |
|
|
{
|
269 |
|
|
private readonly CodeGenerationTools _code;
|
270 |
|
|
private readonly TypeMapper _typeMapper;
|
271 |
|
|
private readonly MetadataTools _ef;
|
272 |
|
|
|
273 |
|
|
public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
|
274 |
|
|
{
|
275 |
|
|
ArgumentNotNull(code, "code");
|
276 |
|
|
ArgumentNotNull(typeMapper, "typeMapper");
|
277 |
|
|
ArgumentNotNull(ef, "ef");
|
278 |
|
|
|
279 |
|
|
_code = code;
|
280 |
|
|
_typeMapper = typeMapper;
|
281 |
|
|
_ef = ef;
|
282 |
|
|
}
|
283 |
|
|
|
284 |
|
|
public string Property(EdmProperty edmProperty)
|
285 |
|
|
{
|
286 |
|
|
return string.Format(
|
287 |
|
|
CultureInfo.InvariantCulture,
|
288 |
|
|
"{0} {1} {2} {{ {3}get; {4}set; }}",
|
289 |
|
|
Accessibility.ForProperty(edmProperty),
|
290 |
|
|
_typeMapper.GetTypeName(edmProperty.TypeUsage),
|
291 |
|
|
_code.Escape(edmProperty),
|
292 |
|
|
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
|
293 |
|
|
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
|
294 |
|
|
}
|
295 |
|
|
|
296 |
|
|
public string NavigationProperty(NavigationProperty navProp)
|
297 |
|
|
{
|
298 |
|
|
var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
|
299 |
|
|
return string.Format(
|
300 |
|
|
CultureInfo.InvariantCulture,
|
301 |
|
|
"{0} {1} {2} {{ {3}get; {4}set; }}",
|
302 |
|
|
AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
|
303 |
|
|
navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
|
304 |
|
|
_code.Escape(navProp),
|
305 |
|
|
_code.SpaceAfter(Accessibility.ForGetter(navProp)),
|
306 |
|
|
_code.SpaceAfter(Accessibility.ForSetter(navProp)));
|
307 |
|
|
}
|
308 |
|
|
|
309 |
|
|
public string AccessibilityAndVirtual(string accessibility)
|
310 |
|
|
{
|
311 |
|
|
return accessibility + (accessibility != "private" ? " virtual" : "");
|
312 |
|
|
}
|
313 |
|
|
|
314 |
|
|
public string EntityClassOpening(EntityType entity)
|
315 |
|
|
{
|
316 |
|
|
return string.Format(
|
317 |
|
|
CultureInfo.InvariantCulture,
|
318 |
|
|
"{0} {1}partial class {2}{3}",
|
319 |
|
|
Accessibility.ForType(entity),
|
320 |
|
|
_code.SpaceAfter(_code.AbstractOption(entity)),
|
321 |
|
|
_code.Escape(entity),
|
322 |
|
|
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
|
323 |
|
|
}
|
324 |
|
|
|
325 |
|
|
public string EnumOpening(SimpleType enumType)
|
326 |
|
|
{
|
327 |
|
|
return string.Format(
|
328 |
|
|
CultureInfo.InvariantCulture,
|
329 |
|
|
"{0} enum {1} : {2}",
|
330 |
|
|
Accessibility.ForType(enumType),
|
331 |
|
|
_code.Escape(enumType),
|
332 |
|
|
_code.Escape(_typeMapper.UnderlyingClrType(enumType)));
|
333 |
|
|
}
|
334 |
|
|
|
335 |
|
|
public void WriteFunctionParameters(EdmFunction edmFunction, Action<string, string, string, string> writeParameter)
|
336 |
|
|
{
|
337 |
|
|
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
|
338 |
|
|
foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
|
339 |
|
|
{
|
340 |
|
|
var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
|
341 |
|
|
var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
|
342 |
|
|
var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
|
343 |
|
|
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
|
344 |
|
|
}
|
345 |
|
|
}
|
346 |
|
|
|
347 |
|
|
public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
|
348 |
|
|
{
|
349 |
|
|
var parameters = _typeMapper.GetParameters(edmFunction);
|
350 |
|
|
|
351 |
|
|
return string.Format(
|
352 |
|
|
CultureInfo.InvariantCulture,
|
353 |
|
|
"{0} IQueryable<{1}> {2}({3})",
|
354 |
|
|
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
|
355 |
|
|
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
|
356 |
|
|
_code.Escape(edmFunction),
|
357 |
|
|
string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
|
358 |
|
|
}
|
359 |
|
|
|
360 |
|
|
public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
|
361 |
|
|
{
|
362 |
|
|
var parameters = _typeMapper.GetParameters(edmFunction);
|
363 |
|
|
|
364 |
|
|
return string.Format(
|
365 |
|
|
CultureInfo.InvariantCulture,
|
366 |
|
|
"return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
|
367 |
|
|
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
|
368 |
|
|
edmFunction.NamespaceName,
|
369 |
|
|
edmFunction.Name,
|
370 |
|
|
string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
|
371 |
|
|
_code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
|
372 |
|
|
}
|
373 |
|
|
|
374 |
|
|
public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
|
375 |
|
|
{
|
376 |
|
|
var parameters = _typeMapper.GetParameters(edmFunction);
|
377 |
|
|
var returnType = _typeMapper.GetReturnType(edmFunction);
|
378 |
|
|
|
379 |
|
|
var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
|
380 |
|
|
if (includeMergeOption)
|
381 |
|
|
{
|
382 |
|
|
paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
|
383 |
|
|
}
|
384 |
|
|
|
385 |
|
|
return string.Format(
|
386 |
|
|
CultureInfo.InvariantCulture,
|
387 |
|
|
"{0} {1} {2}({3})",
|
388 |
|
|
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
|
389 |
|
|
returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
|
390 |
|
|
_code.Escape(edmFunction),
|
391 |
|
|
paramList);
|
392 |
|
|
}
|
393 |
|
|
|
394 |
|
|
public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
|
395 |
|
|
{
|
396 |
|
|
var parameters = _typeMapper.GetParameters(edmFunction);
|
397 |
|
|
var returnType = _typeMapper.GetReturnType(edmFunction);
|
398 |
|
|
|
399 |
|
|
var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
|
400 |
|
|
if (includeMergeOption)
|
401 |
|
|
{
|
402 |
|
|
callParams = ", mergeOption" + callParams;
|
403 |
|
|
}
|
404 |
|
|
|
405 |
|
|
return string.Format(
|
406 |
|
|
CultureInfo.InvariantCulture,
|
407 |
|
|
"return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
|
408 |
|
|
returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
|
409 |
|
|
edmFunction.Name,
|
410 |
|
|
callParams);
|
411 |
|
|
}
|
412 |
|
|
|
413 |
|
|
public string DbSet(EntitySet entitySet)
|
414 |
|
|
{
|
415 |
|
|
return string.Format(
|
416 |
|
|
CultureInfo.InvariantCulture,
|
417 |
|
|
"{0} virtual DbSet<{1}> {2} {{ get; set; }}",
|
418 |
|
|
Accessibility.ForReadOnlyProperty(entitySet),
|
419 |
|
|
_typeMapper.GetTypeName(entitySet.ElementType),
|
420 |
|
|
_code.Escape(entitySet));
|
421 |
|
|
}
|
422 |
|
|
|
423 |
|
|
public string UsingDirectives(bool inHeader, bool includeCollections = true)
|
424 |
|
|
{
|
425 |
|
|
return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
|
426 |
|
|
? string.Format(
|
427 |
|
|
CultureInfo.InvariantCulture,
|
428 |
|
|
"{0}using System;{1}" +
|
429 |
|
|
"{2}",
|
430 |
|
|
inHeader ? Environment.NewLine : "",
|
431 |
|
|
includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
|
432 |
|
|
inHeader ? "" : Environment.NewLine)
|
433 |
|
|
: "";
|
434 |
|
|
}
|
435 |
|
|
}
|
436 |
|
|
|
437 |
|
|
public class TypeMapper
|
438 |
|
|
{
|
439 |
|
|
private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
|
440 |
|
|
|
441 |
|
|
private readonly System.Collections.IList _errors;
|
442 |
|
|
private readonly CodeGenerationTools _code;
|
443 |
|
|
private readonly MetadataTools _ef;
|
444 |
|
|
|
445 |
|
|
public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
|
446 |
|
|
{
|
447 |
|
|
ArgumentNotNull(code, "code");
|
448 |
|
|
ArgumentNotNull(ef, "ef");
|
449 |
|
|
ArgumentNotNull(errors, "errors");
|
450 |
|
|
|
451 |
|
|
_code = code;
|
452 |
|
|
_ef = ef;
|
453 |
|
|
_errors = errors;
|
454 |
|
|
}
|
455 |
|
|
|
456 |
|
|
public static string FixNamespaces(string typeName)
|
457 |
|
|
{
|
458 |
|
|
return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
|
459 |
|
|
}
|
460 |
|
|
|
461 |
|
|
public string GetTypeName(TypeUsage typeUsage)
|
462 |
|
|
{
|
463 |
|
|
return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
|
464 |
|
|
}
|
465 |
|
|
|
466 |
|
|
public string GetTypeName(EdmType edmType)
|
467 |
|
|
{
|
468 |
|
|
return GetTypeName(edmType, isNullable: null, modelNamespace: null);
|
469 |
|
|
}
|
470 |
|
|
|
471 |
|
|
public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
|
472 |
|
|
{
|
473 |
|
|
return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
|
474 |
|
|
}
|
475 |
|
|
|
476 |
|
|
public string GetTypeName(EdmType edmType, string modelNamespace)
|
477 |
|
|
{
|
478 |
|
|
return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
|
479 |
|
|
}
|
480 |
|
|
|
481 |
|
|
public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
|
482 |
|
|
{
|
483 |
|
|
if (edmType == null)
|
484 |
|
|
{
|
485 |
|
|
return null;
|
486 |
|
|
}
|
487 |
|
|
|
488 |
|
|
var collectionType = edmType as CollectionType;
|
489 |
|
|
if (collectionType != null)
|
490 |
|
|
{
|
491 |
|
|
return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
|
492 |
|
|
}
|
493 |
|
|
|
494 |
|
|
var typeName = _code.Escape(edmType.MetadataProperties
|
495 |
|
|
.Where(p => p.Name == ExternalTypeNameAttributeName)
|
496 |
|
|
.Select(p => (string)p.Value)
|
497 |
|
|
.FirstOrDefault())
|
498 |
|
|
?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
|
499 |
|
|
_code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
|
500 |
|
|
_code.Escape(edmType));
|
501 |
|
|
|
502 |
|
|
if (edmType is StructuralType)
|
503 |
|
|
{
|
504 |
|
|
return typeName;
|
505 |
|
|
}
|
506 |
|
|
|
507 |
|
|
if (edmType is SimpleType)
|
508 |
|
|
{
|
509 |
|
|
var clrType = UnderlyingClrType(edmType);
|
510 |
|
|
if (!IsEnumType(edmType))
|
511 |
|
|
{
|
512 |
|
|
typeName = _code.Escape(clrType);
|
513 |
|
|
}
|
514 |
|
|
|
515 |
|
|
typeName = FixNamespaces(typeName);
|
516 |
|
|
|
517 |
|
|
return clrType.IsValueType && isNullable == true ?
|
518 |
|
|
String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
|
519 |
|
|
typeName;
|
520 |
|
|
}
|
521 |
|
|
|
522 |
|
|
throw new ArgumentException("edmType");
|
523 |
|
|
}
|
524 |
|
|
|
525 |
|
|
public Type UnderlyingClrType(EdmType edmType)
|
526 |
|
|
{
|
527 |
|
|
ArgumentNotNull(edmType, "edmType");
|
528 |
|
|
|
529 |
|
|
var primitiveType = edmType as PrimitiveType;
|
530 |
|
|
if (primitiveType != null)
|
531 |
|
|
{
|
532 |
|
|
return primitiveType.ClrEquivalentType;
|
533 |
|
|
}
|
534 |
|
|
|
535 |
|
|
if (IsEnumType(edmType))
|
536 |
|
|
{
|
537 |
|
|
return GetEnumUnderlyingType(edmType).ClrEquivalentType;
|
538 |
|
|
}
|
539 |
|
|
|
540 |
|
|
return typeof(object);
|
541 |
|
|
}
|
542 |
|
|
|
543 |
|
|
public object GetEnumMemberValue(MetadataItem enumMember)
|
544 |
|
|
{
|
545 |
|
|
ArgumentNotNull(enumMember, "enumMember");
|
546 |
|
|
|
547 |
|
|
var valueProperty = enumMember.GetType().GetProperty("Value");
|
548 |
|
|
return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
|
549 |
|
|
}
|
550 |
|
|
|
551 |
|
|
public string GetEnumMemberName(MetadataItem enumMember)
|
552 |
|
|
{
|
553 |
|
|
ArgumentNotNull(enumMember, "enumMember");
|
554 |
|
|
|
555 |
|
|
var nameProperty = enumMember.GetType().GetProperty("Name");
|
556 |
|
|
return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
|
557 |
|
|
}
|
558 |
|
|
|
559 |
|
|
public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
|
560 |
|
|
{
|
561 |
|
|
ArgumentNotNull(enumType, "enumType");
|
562 |
|
|
|
563 |
|
|
var membersProperty = enumType.GetType().GetProperty("Members");
|
564 |
|
|
return membersProperty != null
|
565 |
|
|
? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
|
566 |
|
|
: Enumerable.Empty<MetadataItem>();
|
567 |
|
|
}
|
568 |
|
|
|
569 |
|
|
public bool EnumIsFlags(EdmType enumType)
|
570 |
|
|
{
|
571 |
|
|
ArgumentNotNull(enumType, "enumType");
|
572 |
|
|
|
573 |
|
|
var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
|
574 |
|
|
return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
|
575 |
|
|
}
|
576 |
|
|
|
577 |
|
|
public bool IsEnumType(GlobalItem edmType)
|
578 |
|
|
{
|
579 |
|
|
ArgumentNotNull(edmType, "edmType");
|
580 |
|
|
|
581 |
|
|
return edmType.GetType().Name == "EnumType";
|
582 |
|
|
}
|
583 |
|
|
|
584 |
|
|
public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
|
585 |
|
|
{
|
586 |
|
|
ArgumentNotNull(enumType, "enumType");
|
587 |
|
|
|
588 |
|
|
return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
|
589 |
|
|
}
|
590 |
|
|
|
591 |
|
|
public string CreateLiteral(object value)
|
592 |
|
|
{
|
593 |
|
|
if (value == null || value.GetType() != typeof(TimeSpan))
|
594 |
|
|
{
|
595 |
|
|
return _code.CreateLiteral(value);
|
596 |
|
|
}
|
597 |
|
|
|
598 |
|
|
return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
|
599 |
|
|
}
|
600 |
|
|
|
601 |
|
|
public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
|
602 |
|
|
{
|
603 |
|
|
ArgumentNotNull(types, "types");
|
604 |
|
|
ArgumentNotNull(sourceFile, "sourceFile");
|
605 |
|
|
|
606 |
|
|
var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
|
607 |
|
|
if (types.Any(item => !hash.Add(item)))
|
608 |
|
|
{
|
609 |
|
|
_errors.Add(
|
610 |
|
|
new CompilerError(sourceFile, -1, -1, "6023",
|
611 |
|
|
String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
|
612 |
|
|
return false;
|
613 |
|
|
}
|
614 |
|
|
return true;
|
615 |
|
|
}
|
616 |
|
|
|
617 |
|
|
public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
|
618 |
|
|
{
|
619 |
|
|
return GetItemsToGenerate<SimpleType>(itemCollection)
|
620 |
|
|
.Where(e => IsEnumType(e));
|
621 |
|
|
}
|
622 |
|
|
|
623 |
|
|
public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
|
624 |
|
|
{
|
625 |
|
|
return itemCollection
|
626 |
|
|
.OfType<T>()
|
627 |
|
|
.Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
|
628 |
|
|
.OrderBy(i => i.Name);
|
629 |
|
|
}
|
630 |
|
|
|
631 |
|
|
public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
|
632 |
|
|
{
|
633 |
|
|
return itemCollection
|
634 |
|
|
.Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
|
635 |
|
|
.Select(g => GetGlobalItemName(g));
|
636 |
|
|
}
|
637 |
|
|
|
638 |
|
|
public string GetGlobalItemName(GlobalItem item)
|
639 |
|
|
{
|
640 |
|
|
if (item is EdmType)
|
641 |
|
|
{
|
642 |
|
|
return ((EdmType)item).Name;
|
643 |
|
|
}
|
644 |
|
|
else
|
645 |
|
|
{
|
646 |
|
|
return ((EntityContainer)item).Name;
|
647 |
|
|
}
|
648 |
|
|
}
|
649 |
|
|
|
650 |
|
|
public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
|
651 |
|
|
{
|
652 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
|
653 |
|
|
}
|
654 |
|
|
|
655 |
|
|
public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
|
656 |
|
|
{
|
657 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
|
658 |
|
|
}
|
659 |
|
|
|
660 |
|
|
public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
|
661 |
|
|
{
|
662 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
|
663 |
|
|
}
|
664 |
|
|
|
665 |
|
|
public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
|
666 |
|
|
{
|
667 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
|
668 |
|
|
}
|
669 |
|
|
|
670 |
|
|
public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
|
671 |
|
|
{
|
672 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
|
673 |
|
|
}
|
674 |
|
|
|
675 |
|
|
public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
|
676 |
|
|
{
|
677 |
|
|
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
|
678 |
|
|
}
|
679 |
|
|
|
680 |
|
|
public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
|
681 |
|
|
{
|
682 |
|
|
return type.NavigationProperties.Where(np => np.DeclaringType == type);
|
683 |
|
|
}
|
684 |
|
|
|
685 |
|
|
public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
|
686 |
|
|
{
|
687 |
|
|
return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
|
688 |
|
|
}
|
689 |
|
|
|
690 |
|
|
public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
|
691 |
|
|
{
|
692 |
|
|
ArgumentNotNull(edmFunction, "edmFunction");
|
693 |
|
|
|
694 |
|
|
var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
|
695 |
|
|
return returnParamsProperty == null
|
696 |
|
|
? edmFunction.ReturnParameter
|
697 |
|
|
: ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
|
698 |
|
|
}
|
699 |
|
|
|
700 |
|
|
public bool IsComposable(EdmFunction edmFunction)
|
701 |
|
|
{
|
702 |
|
|
ArgumentNotNull(edmFunction, "edmFunction");
|
703 |
|
|
|
704 |
|
|
var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
|
705 |
|
|
return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
|
706 |
|
|
}
|
707 |
|
|
|
708 |
|
|
public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
|
709 |
|
|
{
|
710 |
|
|
return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
|
711 |
|
|
}
|
712 |
|
|
|
713 |
|
|
public TypeUsage GetReturnType(EdmFunction edmFunction)
|
714 |
|
|
{
|
715 |
|
|
var returnParam = GetReturnParameter(edmFunction);
|
716 |
|
|
return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
|
717 |
|
|
}
|
718 |
|
|
|
719 |
|
|
public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
|
720 |
|
|
{
|
721 |
|
|
var returnType = GetReturnType(edmFunction);
|
722 |
|
|
return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
|
723 |
|
|
}
|
724 |
|
|
}
|
725 |
|
|
|
726 |
|
|
public static void ArgumentNotNull<T>(T arg, string name) where T : class
|
727 |
|
|
{
|
728 |
|
|
if (arg == null)
|
729 |
|
|
{
|
730 |
|
|
throw new ArgumentNullException(name);
|
731 |
|
|
}
|
732 |
|
|
}
|
733 |
|
|
#> |