fork download
  1. <#
  2. // imaginarydevelopment.blogspot.com
  3. // You can use this text template to customize object layer code generation for
  4. // applications that use the Entity Framework. The template generates code based on an .edmx file.
  5. // Before using this template, note the following:
  6. //
  7. // *The name of the text template file will determine the name of the code file it generates.
  8. // For example, if the text template is named TextTemplate.tt, the generated file will be named
  9. // TextTemplate.vb or TextTemplate.cs.
  10. // *The Custom Tool property of the targeted .edmx file must be empty. For more information,
  11. // see .edmx File Properties (http://go.microsoft.com/fwlink/?LinkId=139299).
  12. // *The SourceCsdlPath initialization below must be set to one of the following:
  13. // 1) the path of the targeted .edmx or .csdl file
  14. // 2) the path of the targeted .edmx or .csdl file relative to the template path
  15. //
  16. // For more detailed information about using this template, see
  17. // How to: Customize Object Layer Code Generation (http://go.microsoft.com/fwlink/?LinkId=139297).
  18. // For general information about text templates, see
  19. // Generating Artifacts by Using Text Templates (http://go.microsoft.com/fwlink/?LinkId=139298)
  20. #>
  21. <#@ template language="C#" debug="false" hostspecific="true"#>
  22. <#@ include file="EF.Utility.CS.ttinclude"#><#@
  23. output extension=".cs"#><#
  24.  
  25. var sharedNamespace="Gtpm.Shared";
  26. var behaviorNamespace=sharedNamespace+".Behaviors";
  27. var dtoNamespace=sharedNamespace+".DataInterfaces";
  28. var mappings= new Dictionary<string,string>{{ "SourceSystem1","SourceSystem"}};
  29. ///http://d...content-available-to-author-only...s.com/2010/01/28/tracing-sql-statements-generated-by-entity-framework/
  30.  
  31. UserSettings userSettings =
  32. new UserSettings
  33. {
  34. SourceCsdlPath = @"GtpmDbModel.edmx",
  35. ReferenceCsdlPaths = new string[] {},
  36. FullyQualifySystemTypes = true,
  37. CreateContextAddToMethods = true,
  38. CamelCaseFields = false,
  39. };
  40.  
  41. ApplyUserSettings(userSettings);
  42. if(Errors.HasErrors)
  43. {
  44. return String.Empty;
  45. }
  46.  
  47. MetadataLoader loader = new MetadataLoader(this);
  48. MetadataTools ef = new MetadataTools(this);
  49. CodeRegion region = new CodeRegion(this);
  50. CodeGenerationTools code = new CodeGenerationTools(this){FullyQualifySystemTypes = userSettings.FullyQualifySystemTypes, CamelCaseFields = userSettings.CamelCaseFields};
  51.  
  52. ItemCollection = loader.CreateEdmItemCollection(SourceCsdlPath, ReferenceCsdlPaths.ToArray());
  53. ModelNamespace = loader.GetModelNamespace(SourceCsdlPath);
  54. string namespaceName = code.VsNamespaceSuggestion();
  55. UpdateObjectNamespaceMap(namespaceName);
  56.  
  57. #>
  58. //------------------------------------------------------------------------------
  59. // <auto-generated>
  60. // <#=GetResourceString("Template_GeneratedCodeCommentLine1")#>
  61. //
  62. // <#=GetResourceString("Template_GeneratedCodeCommentLine2")#>
  63. // <#=GetResourceString("Template_GeneratedCodeCommentLine3")#>
  64. // </auto-generated>
  65. //------------------------------------------------------------------------------
  66.  
  67. using System;
  68. using System.Data.Objects;
  69. using System.Data.Objects.DataClasses;
  70. using System.Data.EntityClient;
  71. using System.Collections.Generic;
  72. using System.ComponentModel;
  73. using System.Linq;
  74. using System.Linq.Expressions;
  75. using System.Xml.Serialization;
  76. using System.Runtime.Serialization;
  77.  
  78. using <#=dtoNamespace#>;
  79.  
  80. [assembly: EdmSchemaAttribute()]
  81. <#
  82. ////////
  83. //////// Write Relationship Attributes
  84. ////////
  85. region.Begin(GetResourceString("Template_RegionRelationships"));
  86. bool first = true;
  87. foreach (AssociationType association in GetSourceSchemaTypes<AssociationType>())
  88. {
  89. if (first)
  90. {
  91. WriteLine(string.Empty);
  92. first = false;
  93. }
  94. #>
  95. [assembly: EdmRelationshipAttribute("<#=association.NamespaceName#>", "<#=association.Name#>", "<#=EndName(association, 0)#>", <#=EndMultiplicity(association, 0, code)#>, typeof(<#=EscapeEndTypeName(association, 0, code)#>), "<#=EndName(association, 1)#>", <#=EndMultiplicity(association, 1, code)#>, typeof(<#=EscapeEndTypeName(association, 1, code)#>)<#=code.StringBefore(", ", association.IsForeignKey ? "true" : null)#>)]
  96. <#
  97. }
  98. region.End();
  99.  
  100. if (!String.IsNullOrEmpty(namespaceName))
  101. {
  102. #>
  103.  
  104. namespace <#=namespaceName#>
  105. {
  106. <#
  107. PushIndent(CodeRegion.GetIndent(1));
  108. }
  109.  
  110. ////////
  111. //////// Write EntityContainer and ObjectContext classes.
  112. ////////
  113.  
  114. region.Begin(GetResourceString("Template_RegionContexts"));
  115. foreach (EntityContainer container in GetSourceSchemaTypes<EntityContainer>())
  116. {
  117. #>
  118.  
  119. /// <summary>
  120. /// <#=SummaryComment(container)#>
  121. /// </summary><#=LongDescriptionCommentElement(container, region.CurrentIndentLevel)#>
  122. <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : ObjectContext
  123. <# foreach(EntityType entity in GetSourceSchemaTypes<EntityType>().OrderBy(e => e.Name))
  124. {
  125. var keys=entity.Properties.Where(p=>p.DeclaringType==entity).Cast<EdmProperty>().Where(p=>ef.IsKey(p));
  126. var keyTypes=keys.Select(k=>MultiSchemaEscape(k.TypeUsage,code)).Aggregate((s1,s2)=>s1+","+s2);
  127. #>
  128. ,<#=behaviorNamespace#>.IRepository<I<#=code.Escape(entity)#>>,<#=behaviorNamespace#>.IRepository<<#=code.Escape(entity)#>DTO,Tuple<<#=keyTypes#>>>
  129. <# }#>
  130.  
  131. {
  132.  
  133. #region <#=GetResourceString("Template_RegionConstructors")#>
  134.  
  135. /// <summary>
  136. /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextDefaultCtorComment"), container.Name, container.Name)#>
  137. /// </summary>
  138. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  139. public <#=code.Escape(container)#>() : base("name=<#=container.Name#>", "<#=container.Name#>")
  140. {
  141. <#
  142. WriteLazyLoadingEnabled(container);
  143. #>
  144. OnContextCreated();
  145. }
  146.  
  147. /// <summary>
  148. /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextCommonCtorComment"), container.Name)#>
  149. /// </summary>
  150. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  151. public <#=code.Escape(container)#>(string connectionString) : base(connectionString, "<#=container.Name#>")
  152. {
  153. <#
  154. WriteLazyLoadingEnabled(container);
  155. #>
  156. OnContextCreated();
  157. }
  158.  
  159. /// <summary>
  160. /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextCommonCtorComment"), container.Name)#>
  161. /// </summary>
  162. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  163. public <#=code.Escape(container)#>(EntityConnection entityConnection) : base(entityConnection, "<#=container.Name#>")
  164. {
  165. <#
  166. WriteLazyLoadingEnabled(container);
  167. #>
  168. OnContextCreated();
  169. }
  170.  
  171. #endregion <#=GetResourceString("Template_RegionConstructors")#>
  172.  
  173. #region <#=GetResourceString("Template_RegionPartialMethods")#>
  174.  
  175. partial void OnContextCreated();
  176.  
  177. #endregion <#=GetResourceString("Template_RegionPartialMethods")#>
  178.  
  179. <#
  180. ////////
  181. //////// Write EntityContainer and ObjectContext ObjectSet properties.
  182. ////////
  183. region.Begin(GetResourceString("Template_RegionObjectSetProperties"));
  184. foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
  185. {
  186. VerifyEntityTypeAndSetAccessibilityCompatability(set);
  187. #>
  188.  
  189. /// <summary>
  190. /// <#=SummaryComment(set)#>
  191. /// </summary><#=LongDescriptionCommentElement(set, region.CurrentIndentLevel)#>
  192. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  193. <#=code.SpaceAfter(NewModifier(set))#><#=Accessibility.ForReadOnlyProperty(set)#> ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.Escape(set)#>
  194. {
  195. get
  196. {
  197. if ((<#=code.FieldName(set)#> == null))
  198. {
  199. <#=code.FieldName(set)#> = base.CreateObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>");
  200. }
  201. return <#=code.FieldName(set)#>;
  202. }
  203. }
  204. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  205. private ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.FieldName(set)#>;
  206. <#
  207. }
  208. region.End(); //Object Set properties region
  209.  
  210.  
  211.  
  212. ////////
  213. //////// Write EntityContainer and ObjectContext AddTo<EntitySet> methods.
  214. ////////
  215. //////// AddTo methods are no longer necessary since the EntitySet properties return
  216. //////// an ObjectSet<T> object, which has already has an Add method.
  217. ////////
  218. //////// AddTo methods are generated here for backwards compatibility reasons only.
  219. //////// Set the CreateContextAddToMethods property of the UserSettings object to false
  220. //////// to turn off generation of the AddTo methods.
  221. ////////
  222. region.Begin(GetResourceString("Template_RegionAddToMethods"));
  223. IEnumerable<EntitySet> addToMethods = CreateContextAddToMethods.Value ? container.BaseEntitySets.OfType<EntitySet>() : Enumerable.Empty<EntitySet>();
  224. foreach (EntitySet set in addToMethods)
  225. {
  226. string parameterName = code.Escape(FixParameterName(set.ElementType.Name, code));
  227. #>
  228.  
  229. /// <summary>
  230. /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_GenCommentAddToMethodCs"), set.Name)#>
  231. /// </summary>
  232. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  233. <#=Accessibility.ForType(set.ElementType)#> void AddTo<#=set.Name#>(<#=MultiSchemaEscape(set.ElementType, code)#> <#=parameterName#>)
  234. {
  235. base.AddObject("<#=set.Name#>", <#=parameterName#>);
  236. }
  237. <#
  238. }
  239. region.End();
  240. WriteLine("//#endregion"+ GetResourceString("Template_RegionAddToMethods"));
  241.  
  242. ////////
  243. //////// Write EntityContainer and ObjectContext Function Import methods.
  244. ////////
  245. region.Begin(GetResourceString("Template_RegionFunctionImports"));
  246. foreach (EdmFunction edmFunction in container.FunctionImports)
  247. {
  248.  
  249. IEnumerable<FunctionImportParameter> parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
  250. string paramList = string.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
  251. TypeUsage returnType = edmFunction.ReturnParameter == null ? null : ef.GetElementType(edmFunction.ReturnParameter.TypeUsage);
  252. #>
  253.  
  254. /// <summary>
  255. /// <#=SummaryComment(edmFunction)#>
  256. /// </summary><#=LongDescriptionCommentElement(edmFunction, region.CurrentIndentLevel)#><#=ParameterComments(parameters.Select(p => new Tuple<string, string>(p.RawFunctionParameterName, SummaryComment(p.Source))), region.CurrentIndentLevel)#>
  257. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  258. <#=code.SpaceAfter(NewModifier(edmFunction))#><#=Accessibility.ForMethod(edmFunction)#> <#=returnType == null ? "int" : "ObjectResult<" + MultiSchemaEscape(returnType, code) + ">"#> <#=code.Escape(edmFunction)#>(<#=paramList#>)
  259. {
  260. <#
  261. foreach (FunctionImportParameter parameter in parameters)
  262. {
  263. if (!parameter.NeedsLocalVariable)
  264. continue;
  265. #>
  266. ObjectParameter <#=parameter.LocalVariableName#>;
  267. if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>)
  268. {
  269. <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>);
  270. }
  271. else
  272. {
  273. <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>));
  274. }
  275.  
  276. <#
  277. }
  278. #>
  279. return base.ExecuteFunction<#=returnType == null ? "" : "<" + MultiSchemaEscape(returnType, code) + ">"#>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
  280. }
  281. <#
  282. if(returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType)
  283. {
  284. #>
  285. /// <summary>
  286. /// <#=SummaryComment(edmFunction)#>
  287. /// </summary><#=LongDescriptionCommentElement(edmFunction, region.CurrentIndentLevel)#>
  288. /// <param name="mergeOption"></param><#=ParameterComments(parameters.Select(p => new Tuple<string, string>(p.RawFunctionParameterName, SummaryComment(p.Source))), region.CurrentIndentLevel)#>
  289. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  290. <#=code.SpaceAfter(NewModifier(edmFunction))#><#=Accessibility.ForMethod(edmFunction)#> <#=returnType == null ? "int" : "ObjectResult<" + MultiSchemaEscape(returnType, code) + ">"#> <#=code.Escape(edmFunction)#>(<#=code.StringAfter(paramList, ", ")#>MergeOption mergeOption)
  291. {
  292. <#
  293. foreach (FunctionImportParameter parameter in parameters)
  294. {
  295. if (!parameter.NeedsLocalVariable)
  296. continue;
  297. #>
  298. ObjectParameter <#=parameter.LocalVariableName#>;
  299. if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>)
  300. {
  301. <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>);
  302. }
  303. else
  304. {
  305. <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>));
  306. }
  307.  
  308. <#
  309. }
  310. #>
  311. return base.<#=returnType == null ? "ExecuteFunction" : "ExecuteFunction<" + MultiSchemaEscape(returnType, code) + ">"#>("<#=edmFunction.Name#>", mergeOption<#=code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
  312. }
  313. <#
  314. }
  315. }
  316. region.End();
  317. #> #region IRepositories
  318.  
  319. public bool DoTrace {get{return InterceptingProvider.DoTrace;}set{InterceptingProvider.DoTrace=value;}}
  320. readonly static TypeChangeVisitor _TypeChangeVisitor = new TypeChangeVisitor(new Dictionary<Type,Type>{
  321. <# foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>().OrderBy(e => e.Name))
  322. {
  323. var typeName=MultiSchemaEscape(set.ElementType,code);
  324. var interfaceName="I"+typeName;
  325. #>
  326. {typeof(<#=interfaceName#>),typeof(<#=typeName#>)},
  327. {typeof(<#=typeName#>DTO),typeof(<#=typeName#>)},
  328. <# }#>
  329. });
  330. static bool _useExpressionWriter;
  331. #if DEBUG
  332. public static bool UseExpressionWriter{get{return _useExpressionWriter; }set{_useExpressionWriter=value;}}
  333. #endif
  334. IQueryable<T> GetInterceptor<T>(ObjectSet<T> set) where T:class
  335. {
  336. IQueryable<T> provider;
  337. #if DEBUG
  338. if(UseExpressionWriter)
  339. provider=InterceptingProvider.Intercept( new ExpressionWriter(new DebugTextWriter("Before")),
  340. set,_TypeChangeVisitor ,new ExpressionWriter(new DebugTextWriter("After")));
  341. else
  342. #endif
  343. provider=InterceptingProvider.Intercept(set,_TypeChangeVisitor );
  344.  
  345. return provider;
  346. }
  347. //foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
  348. <# foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>().OrderBy(e => e.Name))
  349. {
  350. var typeName=MultiSchemaEscape(set.ElementType,code);
  351. var interfaceName="I"+typeName;
  352. var keys=set.ElementType.Properties.Where(p=>p.DeclaringType==set.ElementType).Cast<EdmProperty>().Where(p=>ef.IsKey(p));
  353. var locator=keys
  354. .Select(p=>MultiSchemaEscape(p.TypeUsage,code)+" "+p.Name).Aggregate((s1,s2)=>s1+","+s2);
  355. Func<string,string> setKeys=t=>keys.Select((p,index)=>t+"."+p.Name+" =keys.Item"+(index+1)+";").Aggregate((s1,s2)=>s1+Environment.NewLine+s2);
  356. //Func<string,string> setKeys=t=>keys.Select(p=>t+"."+p.Name+" = "+p.Name+";").Aggregate((s1,s2)=>s1+Environment.NewLine+s2);
  357. var keyTypes=keys.Select(k=>MultiSchemaEscape(k.TypeUsage,code)).Aggregate((s1,s2)=>s1+","+s2);
  358. #>
  359. /// <summary>
  360. /// Inserts
  361. /// </summary>
  362. <#=interfaceName#> <#=behaviorNamespace#>.IRepository<<#=interfaceName#>>.Create(<#=interfaceName#> item)
  363. {
  364. var concrete=Gtpm.Shared.SyntaxSugar.Helpers.MapUsingSerializer<<#=typeName#>>(item);
  365. this.AddTo<#=code.Escape(set)#>(concrete);
  366. this.SaveChanges();
  367. return concrete;
  368. }
  369. void <#=behaviorNamespace#>.IRepository<<#=interfaceName#>>.Delete(<#=interfaceName#> item)
  370. {
  371. var stub= new <#=typeName#>(){
  372.  
  373. <#
  374. foreach (EdmProperty prop in set.ElementType.Properties.Where(p => p.DeclaringType == set.ElementType).Cast<EdmProperty>()
  375. .Where(p=>ef.IsKey(p)) )
  376. { #>
  377. <#=prop.Name#> = item.<#=mappings.ContainsKey(prop.Name)?mappings[prop.Name]:prop.Name#>,
  378. <# } #>
  379. };
  380. this.<#=code.Escape(set)#>.Attach(stub);
  381. this.DeleteObject(stub);
  382. this.SaveChanges();
  383. }
  384. /// <summary>
  385. /// Create
  386. /// </summary>
  387. <#=interfaceName#> <#=behaviorNamespace#>.IRepository<<#=interfaceName#>>.Update(<#=interfaceName#> item, IEnumerable<string> propertyList)
  388. {
  389. var concrete=Gtpm.Shared.SyntaxSugar.Helpers.MapUsingSerializer<<#=typeName#>>(item);
  390. this.<#=code.Escape(set)#>.Attach(concrete);
  391. foreach(var p in propertyList)
  392. ObjectStateManager.GetObjectStateEntry(concrete).SetModifiedProperty(p);
  393. this.SaveChanges();
  394. return concrete;
  395. }
  396.  
  397.  
  398. /// <summary>
  399. /// Class to enable business logic to query a source without knowing implementation of the source
  400. /// </summary>
  401. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  402. IQueryable<<#=interfaceName#>> <#=behaviorNamespace#>.IRepository<<#=interfaceName#>>.Query()
  403. {
  404. return GetInterceptor(<#=code.Escape(set)#>);
  405.  
  406. }
  407. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  408. IEnumerable<I<#=MultiSchemaEscape(set.ElementType, code)#>> <#=behaviorNamespace#>.IRepository<I<#=MultiSchemaEscape(set.ElementType, code)#>>.Find(Expression<Func<I<#=MultiSchemaEscape(set.ElementType, code)#>,bool>> where)
  409. {
  410. return this.<#=code.Escape(set)#>.Select<<#=typeName#>,<#=interfaceName#>>(u=>u).Where(where);
  411.  
  412. }
  413. <#}#>
  414. #endregion IRepositories
  415.  
  416. }
  417.  
  418. <#
  419. }
  420. region.End();
  421. #>
  422.  
  423. <#
  424. ////////
  425. //////// Write EntityType classes.
  426. ////////
  427. region.Begin(GetResourceString("Template_RegionEntities"));
  428. foreach (EntityType entity in GetSourceSchemaTypes<EntityType>().OrderBy(e => e.Name))
  429. {
  430. #>
  431.  
  432. /// <summary>
  433. /// <#=SummaryComment(entity)#>
  434. /// </summary><#=LongDescriptionCommentElement(entity, region.CurrentIndentLevel)#>
  435. [EdmEntityTypeAttribute(NamespaceName="<#=entity.NamespaceName#>", Name="<#=entity.Name#>")]
  436. [Serializable()]
  437. [DataContractAttribute(IsReference=true)]
  438. <#
  439. foreach (EntityType subType in ItemCollection.GetItems<EntityType>().Where(b => b.BaseType == entity))
  440. {
  441. #>
  442.  
  443. [KnownTypeAttribute(typeof(<#=MultiSchemaEscape(subType, code)#>))]
  444. <#
  445. }
  446. #>
  447. <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#>
  448. : <#=BaseTypeName(entity, code)#>,
  449. <#=dtoNamespace #>.I<#=code.Escape(entity)#>
  450. {
  451. <#
  452. if (!entity.Abstract)
  453. {
  454. WriteFactoryMethod(entity, code);
  455. }
  456.  
  457. region.Begin(GetResourceString("Template_RegionPrimitiveProperties"));
  458. foreach (EdmProperty property in entity.Properties.Where(p => p.DeclaringType == entity && p.TypeUsage.EdmType is PrimitiveType))
  459. {
  460. VerifyGetterAndSetterAccessibilityCompatability(property);
  461. WritePrimitiveTypeProperty(property, code);
  462. }
  463. region.End();
  464.  
  465. region.Begin(GetResourceString("Template_RegionComplexProperties"));
  466. foreach (EdmProperty property in entity.Properties.Where(p => p.DeclaringType == entity && p.TypeUsage.EdmType is ComplexType))
  467. {
  468. VerifyGetterAndSetterAccessibilityCompatability(property);
  469. WriteComplexTypeProperty(property, code);
  470. }
  471. region.End();
  472. #>
  473.  
  474. <#
  475. ////////
  476. //////// Write Navigation Properties.
  477. ////////
  478. region.Begin(GetResourceString("Template_RegionNavigationProperties"));
  479. foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(n => n.DeclaringType == entity))
  480. {
  481. VerifyGetterAndSetterAccessibilityCompatability(navProperty);
  482. #>
  483.  
  484. /// <summary>
  485. /// <#=SummaryComment(navProperty)#>
  486. /// </summary><#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel)#>
  487. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  488. [XmlIgnoreAttribute()]
  489. [SoapIgnoreAttribute()]
  490. [DataMemberAttribute()]
  491. [EdmRelationshipNavigationPropertyAttribute("<#=navProperty.RelationshipType.NamespaceName#>", "<#=navProperty.RelationshipType.Name#>", "<#=navProperty.ToEndMember.Name#>")]
  492. <#
  493. if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
  494. {
  495. #>
  496. <#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> EntityCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=code.Escape(navProperty)#>
  497. {
  498. <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
  499. {
  500. return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>");
  501. }
  502. <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
  503. {
  504. if ((value != null))
  505. {
  506. ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value);
  507. }
  508. }
  509. }
  510. <#
  511. }
  512. else
  513. {
  514. #>
  515. <#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> <#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#> <#=code.Escape(navProperty)#>
  516. {
  517. <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
  518. {
  519. return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value;
  520. }
  521. <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
  522. {
  523. ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value = value;
  524. }
  525. }
  526. <#
  527. string refPropertyName = navProperty.Name + "Reference";
  528. if (entity.Members.Any(m => m.Name == refPropertyName))
  529. {
  530. // 6017 is the same error number that EntityClassGenerator uses.
  531. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6017", String.Format(CultureInfo.CurrentCulture,
  532. GetResourceString("Template_ConflictingGeneratedNavPropName"),
  533. navProperty.Name, entity.FullName, refPropertyName)));
  534. }
  535. #>
  536. /// <summary>
  537. /// <#=SummaryComment(navProperty)#>
  538. /// </summary><#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel)#>
  539. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  540. [BrowsableAttribute(false)]
  541. [DataMemberAttribute()]
  542. <#=Accessibility.ForProperty(navProperty)#> EntityReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=refPropertyName#>
  543. {
  544. <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
  545. {
  546. return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>");
  547. }
  548. <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
  549. {
  550. if ((value != null))
  551. {
  552. ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value);
  553. }
  554. }
  555. }
  556. <#
  557. }
  558. }
  559. region.End();
  560. #>
  561. }
  562. <# }
  563. region.End();
  564.  
  565. ////////
  566. //////// Write ComplexType classes.
  567. ////////
  568. region.Begin(GetResourceString("Template_RegionComplexTypes"));
  569. foreach (ComplexType complex in GetSourceSchemaTypes<ComplexType>().OrderBy(c => c.Name))
  570. {
  571. #>
  572. //Complex
  573. /// <summary>
  574. /// <#=SummaryComment(complex)#>
  575. /// </summary><#=LongDescriptionCommentElement(complex, region.CurrentIndentLevel)#>
  576. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  577. [EdmComplexTypeAttribute(NamespaceName="<#=complex.NamespaceName#>", Name="<#=complex.Name#>")]
  578. [DataContractAttribute(IsReference=true)]
  579. [Serializable()]
  580. <#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> : ComplexObject
  581. {
  582. <#
  583. WriteFactoryMethod(complex, code);
  584. region.Begin(GetResourceString("Template_RegionPrimitiveProperties"));
  585. foreach (EdmProperty property in complex.Properties.Where(p => p.DeclaringType == complex && p.TypeUsage.EdmType is PrimitiveType))
  586. {
  587. VerifyGetterAndSetterAccessibilityCompatability(property);
  588. WritePrimitiveTypeProperty(property, code);
  589. }
  590. region.End();
  591. region.Begin(GetResourceString("Template_RegionComplexProperties"));
  592. foreach (EdmProperty property in complex.Properties.Where(p => p.DeclaringType == complex && p.TypeUsage.EdmType is ComplexType))
  593. {
  594. VerifyGetterAndSetterAccessibilityCompatability(property);
  595. WriteComplexTypeProperty(property, code);
  596. }
  597. region.End();
  598. #>
  599. }
  600. <#
  601. }
  602. region.End();
  603. #>
  604.  
  605. <#
  606. if (!String.IsNullOrEmpty(namespaceName))
  607. {
  608. PopIndent();
  609. #>
  610. }
  611. <#
  612. }
  613. VerifyTypeUniqueness();
  614. #>
  615.  
  616. <#+
  617.  
  618. ////////
  619. //////// Reusable Template Sections
  620. ////////
  621.  
  622. ////////
  623. //////// Write Factory Method.
  624. ////////
  625. private void WriteFactoryMethod(StructuralType structuralType, CodeGenerationTools code)
  626. {
  627. CodeRegion region = new CodeRegion(this, 1);
  628.  
  629. string methodName = "Create" + structuralType.Name;
  630. UniqueIdentifierService uniqueIdentifier = new UniqueIdentifierService();
  631. string instanceName = code.Escape(uniqueIdentifier.AdjustIdentifier((code.CamelCase(structuralType.Name))));
  632. IEnumerable<FactoryMethodParameter> parameters = FactoryMethodParameter.CreateParameters(structuralType.Members.OfType<EdmProperty>().Where(p => IncludePropertyInFactoryMethod(structuralType, p)), uniqueIdentifier, MultiSchemaEscape, code);
  633.  
  634. if (parameters.Count() == 0)
  635. return;
  636.  
  637. if (structuralType.Members.Any(m => m.Name == methodName))
  638. {
  639. // 6029 is the same error number that EntityClassGenerator uses for this conflict.
  640. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6029",
  641. String.Format(CultureInfo.CurrentCulture,
  642. GetResourceString("Template_FactoryMethodNameConflict"), methodName, structuralType.FullName)));
  643. }
  644.  
  645. region.Begin(GetResourceString("Template_RegionFactoryMethod"));
  646. #>
  647.  
  648. /// <summary>
  649. /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_FactoryMethodComment"), structuralType.Name)#>
  650. /// </summary><#=ParameterComments(parameters.Select(p => new Tuple<string, string>(p.RawParameterName, p.ParameterComment)), region.CurrentIndentLevel)#>
  651. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  652. public static <#=code.Escape(structuralType)#> <#=methodName#>(<#=string.Join(", ", parameters.Select(p => p.ParameterType + " " + p.ParameterName).ToArray())#>)
  653. {
  654. <#=code.Escape(structuralType)#> <#=instanceName#> = new <#=code.Escape(structuralType)#>();
  655. <#+
  656. foreach (FactoryMethodParameter parameter in parameters)
  657. {
  658. if (parameter.IsComplexType)
  659. {
  660. // ComplexType initialization.
  661. #>
  662. <#=instanceName#>.<#=code.Escape(parameter.Source)#> = StructuralObject.VerifyComplexObjectIsNotNull(<#=parameter.ParameterName#>, "<#=parameter.Source.Name#>");
  663. <#+
  664. }
  665. else
  666. {
  667. // PrimitiveType initialization.
  668. #>
  669. <#=instanceName#>.<#=code.Escape(parameter.Source)#> = <#=parameter.ParameterName#>;
  670. <#+
  671. }
  672. }
  673. #>
  674. return <#=instanceName#>;
  675. }
  676. <#+
  677. region.End();
  678. }
  679.  
  680.  
  681. ////////
  682. //////// Write PrimitiveType Properties.
  683. ////////
  684. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  685. private void WritePrimitiveTypeProperty(EdmProperty primitiveProperty, CodeGenerationTools code)
  686. {
  687. MetadataTools ef = new MetadataTools(this);
  688. #>
  689.  
  690. /// <summary>
  691. /// <#=SummaryComment(primitiveProperty)#>
  692. /// </summary><#=LongDescriptionCommentElement(primitiveProperty, 1)#>
  693. [EdmScalarPropertyAttribute(EntityKeyProperty=<#=code.CreateLiteral(ef.IsKey(primitiveProperty))#>, IsNullable=<#=code.CreateLiteral(ef.IsNullable(primitiveProperty))#>)]
  694. [DataMemberAttribute()]
  695. [System.CodeDom.Compiler.GeneratedCode("T4","1.0.0.0")]
  696. <#=code.SpaceAfter(NewModifier(primitiveProperty))#><#=Accessibility.ForProperty(primitiveProperty)#> <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.Escape(primitiveProperty)#>
  697. {
  698. <#=code.SpaceAfter(Accessibility.ForGetter(primitiveProperty))#>get
  699. {
  700. <#+ if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
  701. {
  702. #>
  703. return StructuralObject.GetValidValue(<#=code.FieldName(primitiveProperty)#>);
  704. <#+
  705. }
  706. else
  707. {
  708. #>
  709. return <#=code.FieldName(primitiveProperty)#>;
  710. <#+
  711. }
  712. #>
  713. }
  714. <#=code.SpaceAfter(Accessibility.ForSetter((primitiveProperty)))#>set
  715. {
  716. <#+
  717. if (ef.IsKey(primitiveProperty))
  718. {
  719. if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
  720. {
  721. #>
  722. if (!StructuralObject.BinaryEquals(<#=code.FieldName(primitiveProperty)#>, value))
  723. <#+
  724. }
  725. else
  726. {
  727. #>
  728. if (<#=code.FieldName(primitiveProperty)#> != value)
  729. <#+
  730. }
  731. #>
  732. {
  733. <#+
  734. PushIndent(CodeRegion.GetIndent(1));
  735. }
  736. #>
  737. <#=ChangingMethodName(primitiveProperty)#>(value);
  738. ReportPropertyChanging("<#=primitiveProperty.Name#>");
  739. <#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
  740. ReportPropertyChanged("<#=primitiveProperty.Name#>");
  741. <#=ChangedMethodName(primitiveProperty)#>();
  742. <#+
  743. if (ef.IsKey(primitiveProperty))
  744. {
  745. PopIndent();
  746. #>
  747. }
  748. <#+
  749. }
  750. #>
  751. }
  752. }
  753. private <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.FieldName(primitiveProperty)#><#=code.StringBefore(" = ", code.CreateLiteral(primitiveProperty.DefaultValue))#>;
  754. partial void <#=ChangingMethodName(primitiveProperty)#>(<#=code.Escape(primitiveProperty.TypeUsage)#> value);
  755. partial void <#=ChangedMethodName(primitiveProperty)#>();
  756. <#+
  757. }
  758.  
  759. ////////
  760. //////// Write ComplexType Properties.
  761. ////////
  762. private void WriteComplexTypeProperty(EdmProperty complexProperty, CodeGenerationTools code)
  763. {
  764. #>
  765.  
  766. /// <summary>
  767. /// <#=SummaryComment(complexProperty)#>
  768. /// </summary><#=LongDescriptionCommentElement(complexProperty, 1)#>
  769. [EdmComplexPropertyAttribute()]
  770. [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  771. [XmlElement(IsNullable=true)]
  772. [SoapElement(IsNullable=true)]
  773. [DataMemberAttribute()]
  774. <#=code.SpaceAfter(NewModifier(complexProperty))#><#=Accessibility.ForProperty(complexProperty)#> <#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> <#=code.Escape(complexProperty)#>
  775. {
  776. <#=code.SpaceAfter(Accessibility.ForGetter(complexProperty))#>get
  777. {
  778. <#=code.FieldName(complexProperty)#> = GetValidValue(<#=code.FieldName(complexProperty)#>, "<#=complexProperty.Name#>", false, <#=InitializedTrackingField(complexProperty, code)#>);
  779. <#=InitializedTrackingField(complexProperty, code)#> = true;
  780. return <#=code.FieldName(complexProperty)#>;
  781. }
  782. <#=code.SpaceAfter(Accessibility.ForSetter(complexProperty))#>set
  783. {
  784. <#=ChangingMethodName(complexProperty)#>(value);
  785. ReportPropertyChanging("<#=complexProperty.Name#>");
  786. <#=code.FieldName(complexProperty)#> = SetValidValue(<#=code.FieldName(complexProperty)#>, value, "<#=complexProperty.Name#>");
  787. <#=InitializedTrackingField(complexProperty, code)#> = true;
  788. ReportPropertyChanged("<#=complexProperty.Name#>");
  789. <#=ChangedMethodName(complexProperty)#>();
  790. }
  791. }
  792. private <#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> <#=code.FieldName(complexProperty)#>;
  793. private bool <#=InitializedTrackingField(complexProperty, code)#>;
  794. partial void <#=ChangingMethodName(complexProperty)#>(<#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> value);
  795. partial void <#=ChangedMethodName(complexProperty)#>();
  796. <#+
  797. }
  798.  
  799. private void WriteLazyLoadingEnabled(EntityContainer container)
  800. {
  801. string lazyLoadingAttributeValue = null;
  802. string lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";
  803. if(MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue))
  804. {
  805. bool isLazyLoading = false;
  806. if(bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading))
  807. {
  808. #>
  809. this.ContextOptions.LazyLoadingEnabled = <#=isLazyLoading.ToString().ToLowerInvariant()#>;
  810. <#+
  811. }
  812. }
  813. }
  814.  
  815. ////////
  816. //////// Declare Template Public Properties.
  817. ////////
  818. public string SourceCsdlPath{ get; set; }
  819. public string ModelNamespace{ get; set; }
  820. public EdmItemCollection ItemCollection{ get; set; }
  821. public IEnumerable<string> ReferenceCsdlPaths{ get; set; }
  822. public Nullable<bool> CreateContextAddToMethods{ get; set; }
  823. public Dictionary<string, string> EdmToObjectNamespaceMap
  824. {
  825. get { return _edmToObjectNamespaceMap; }
  826. set { _edmToObjectNamespaceMap = value; }
  827. }
  828. public Dictionary<string, string> _edmToObjectNamespaceMap = new Dictionary<string, string>();
  829. public Double SourceEdmVersion
  830. {
  831. get
  832. {
  833. if (ItemCollection != null)
  834. {
  835. return ItemCollection.EdmVersion;
  836. }
  837.  
  838. return 0.0;
  839. }
  840. }
  841.  
  842. ////////
  843. //////// Declare Template Private Properties.
  844. ////////
  845. static System.Resources.ResourceManager ResourceManager
  846. {
  847. get
  848. {
  849. if (_resourceManager == null)
  850. {
  851. System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(System.Data.Entity.Design.MetadataItemCollectionFactory).Assembly);
  852. System.Threading.Interlocked.CompareExchange(ref _resourceManager, resourceManager, null);
  853. }
  854. return _resourceManager;
  855. }
  856. }
  857. static System.Resources.ResourceManager _resourceManager;
  858.  
  859. #>
  860. <#+
  861.  
  862.  
  863. private static string GetResourceString(string resourceName)
  864. {
  865. return ResourceManager.GetString(resourceName,
  866. null); // Take default culture.
  867. }
  868.  
  869.  
  870.  
  871. private void VerifyTypeUniqueness()
  872. {
  873. HashSet<string> hash = new HashSet<string>();
  874. IEnumerable<GlobalItem> allTypes = GetSourceSchemaTypes<GlobalItem>().Where(i => i is StructuralType || i is EntityContainer);
  875.  
  876. foreach (GlobalItem type in allTypes)
  877. {
  878. if (!hash.Add(GetGlobalItemName(type)))
  879. {
  880. // 6034 is the error number used by System.Data.Entity.Design EntityClassGenerator.
  881. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6034",
  882. String.Format(CultureInfo.CurrentCulture,
  883. GetResourceString("Template_DuplicateTopLevelType"),
  884. GetGlobalItemName(type))));
  885. }
  886. }
  887. }
  888.  
  889. protected string GetGlobalItemName(GlobalItem item)
  890. {
  891. if (item is EdmType)
  892. {
  893. // EntityType or ComplexType.
  894. return ((EdmType)item).Name;
  895. }
  896. else
  897. {
  898. // Must be an EntityContainer.
  899. return ((EntityContainer)item).Name;
  900. }
  901. }
  902.  
  903.  
  904.  
  905. void ApplyUserSettings(UserSettings userSettings)
  906. {
  907. // Setup template UserSettings.
  908. if (SourceCsdlPath == null)
  909. {
  910. #if !PREPROCESSED_TEMPLATE
  911. if(userSettings.SourceCsdlPath == "$" + "edmxInputFile" + "$")
  912. {
  913. Errors.Add(new System.CodeDom.Compiler.CompilerError(Host.TemplateFile, 0, 0, "",
  914. GetResourceString("Template_ReplaceVsItemTemplateToken")));
  915. return;
  916. }
  917.  
  918. SourceCsdlPath = Host.ResolvePath(userSettings.SourceCsdlPath);
  919. #else
  920. SourceCsdlPath = userSettings.SourceCsdlPath;
  921. #endif
  922. }
  923.  
  924. // normalize the path, remove ..\ from it
  925. SourceCsdlPath = Path.GetFullPath(SourceCsdlPath);
  926.  
  927.  
  928. if (ReferenceCsdlPaths == null)
  929. {
  930. ReferenceCsdlPaths = userSettings.ReferenceCsdlPaths;
  931. }
  932.  
  933. if (!CreateContextAddToMethods.HasValue)
  934. {
  935. CreateContextAddToMethods = userSettings.CreateContextAddToMethods;
  936. }
  937.  
  938. DefaultSummaryComment = GetResourceString("Template_CommentNoDocumentation");
  939. }
  940.  
  941.  
  942. class UserSettings
  943. {
  944. public string SourceCsdlPath{ get; set; }
  945. public string[] ReferenceCsdlPaths{ get; set; }
  946. public bool FullyQualifySystemTypes{ get; set; }
  947. public bool CreateContextAddToMethods{ get; set; }
  948. public bool CamelCaseFields{ get; set; }
  949. }
  950.  
  951. string MultiSchemaEscape(TypeUsage usage, CodeGenerationTools code)
  952. {
  953. StructuralType structural = usage.EdmType as StructuralType;
  954. if (structural != null)
  955. {
  956. return MultiSchemaEscape(structural, code);
  957. }
  958. return code.Escape(usage);
  959. }
  960.  
  961. string MultiSchemaEscape(StructuralType type, CodeGenerationTools code)
  962. {
  963. if (type.NamespaceName != ModelNamespace)
  964. {
  965. return code.CreateFullName(code.EscapeNamespace(GetObjectNamespace(type.NamespaceName)), code.Escape(type));
  966. }
  967.  
  968. return code.Escape(type);
  969. }
  970.  
  971. string NewModifier(NavigationProperty navigationProperty)
  972. {
  973. Type baseType = typeof(EntityObject);
  974. return NewModifier(baseType, navigationProperty.Name);
  975. }
  976.  
  977. string NewModifier(EdmFunction edmFunction)
  978. {
  979. Type baseType = typeof(ObjectContext);
  980. return NewModifier(baseType, edmFunction.Name);
  981. }
  982.  
  983. string NewModifier(EntitySet set)
  984. {
  985. Type baseType = typeof(ObjectContext);
  986. return NewModifier(baseType, set.Name);
  987. }
  988.  
  989. string NewModifier(EdmProperty property)
  990. {
  991. Type baseType;
  992. if (property.DeclaringType.BuiltInTypeKind == BuiltInTypeKind.EntityType)
  993. {
  994. baseType = typeof(EntityObject);
  995. }
  996. else
  997. {
  998. baseType = typeof(ComplexObject);
  999. }
  1000. return NewModifier(baseType, property.Name);
  1001. }
  1002.  
  1003. string NewModifier(Type type, string memberName)
  1004. {
  1005. if (HasBaseMemberWithMatchingName(type, memberName))
  1006. {
  1007. return "new";
  1008. }
  1009. return string.Empty;
  1010. }
  1011.  
  1012. static bool HasBaseMemberWithMatchingName(Type type, string memberName)
  1013. {
  1014. BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public
  1015. | BindingFlags.Instance | BindingFlags.Static;
  1016. return type.GetMembers(bindingFlags).Where(m => IsVisibleMember(m)).Any(m => m.Name == memberName);
  1017. }
  1018.  
  1019. string ChangingMethodName(EdmMember member)
  1020. {
  1021. return string.Format(CultureInfo.InvariantCulture, "On{0}Changing", member.Name);
  1022. }
  1023.  
  1024. string ChangedMethodName(EdmMember member)
  1025. {
  1026. return string.Format(CultureInfo.InvariantCulture, "On{0}Changed", member.Name);
  1027. }
  1028.  
  1029. string InitializedTrackingField(EdmProperty property, CodeGenerationTools code)
  1030. {
  1031. string namePart = property.Name + "Initialized";
  1032. if (code.CamelCaseFields)
  1033. {
  1034. namePart = code.CamelCase(namePart);
  1035. }
  1036. return "_" + namePart;
  1037. }
  1038.  
  1039. string OptionalNullableParameterForSetValidValue(EdmMember member, CodeGenerationTools code)
  1040. {
  1041. MetadataTools ef = new MetadataTools(this);
  1042. string list = string.Empty;
  1043. if (((PrimitiveType)member.TypeUsage.EdmType).ClrEquivalentType.IsClass)
  1044. {
  1045. MetadataProperty storeGeneratedPatternProperty = null;
  1046. bool isNullable = ef.IsNullable(member.TypeUsage) ||
  1047. (member.MetadataProperties.TryGetValue(MetadataConstants.EDM_ANNOTATION_09_02 + ":StoreGeneratedPattern", false, out storeGeneratedPatternProperty) &&
  1048. Object.Equals(storeGeneratedPatternProperty.Value, "Computed"));
  1049. list += ", " + code.CreateLiteral(isNullable);
  1050. }
  1051. return list;
  1052. }
  1053.  
  1054. static bool IsVisibleMember(MemberInfo memberInfo)
  1055. {
  1056. if (memberInfo is EventInfo)
  1057. {
  1058. EventInfo ei = (EventInfo)memberInfo;
  1059. MethodInfo add = ei.GetAddMethod();
  1060. MethodInfo remove = ei.GetRemoveMethod();
  1061. return IsVisibleMethod(add) || IsVisibleMethod(remove);
  1062. }
  1063. else if (memberInfo is FieldInfo)
  1064. {
  1065. FieldInfo fi = (FieldInfo)memberInfo;
  1066. return !fi.IsPrivate && !fi.IsAssembly;
  1067. }
  1068. else if (memberInfo is MethodBase)
  1069. {
  1070. MethodBase mb = (MethodBase)memberInfo;
  1071. if (mb.IsSpecialName)
  1072. return false;
  1073. return IsVisibleMethod(mb);
  1074. }
  1075. else if (memberInfo is PropertyInfo)
  1076. {
  1077. PropertyInfo pi = (PropertyInfo)memberInfo;
  1078. MethodInfo get = pi.GetGetMethod();
  1079. MethodInfo set = pi.GetSetMethod();
  1080. return IsVisibleMethod(get) || IsVisibleMethod(set);
  1081. }
  1082.  
  1083. return false;
  1084. }
  1085.  
  1086. static bool IsVisibleMethod(MethodBase methodBase)
  1087. {
  1088. if (methodBase == null)
  1089. return false;
  1090.  
  1091. return !methodBase.IsPrivate && !methodBase.IsAssembly;
  1092. }
  1093.  
  1094. IEnumerable<T> GetSourceSchemaTypes<T>() where T : GlobalItem
  1095. {
  1096. if (Path.GetExtension(SourceCsdlPath) != ".edmx")
  1097. {
  1098. return ItemCollection.GetItems<T>().Where(e => e.MetadataProperties.Any(mp => mp.Name == "SchemaSource" && (string)mp.Value == SourceCsdlPath));
  1099. }
  1100. else
  1101. {
  1102. return ItemCollection.GetItems<T>();
  1103. }
  1104. }
  1105.  
  1106. string EndName(AssociationType association, int index)
  1107. {
  1108. return association.AssociationEndMembers[index].Name;
  1109. }
  1110.  
  1111. string EndMultiplicity(AssociationType association, int index, CodeGenerationTools code)
  1112. {
  1113. return code.CreateLiteral(association.AssociationEndMembers[index].RelationshipMultiplicity);
  1114. }
  1115.  
  1116. string EscapeEndTypeName(AssociationType association, int index, CodeGenerationTools code)
  1117. {
  1118. EntityType entity = association.AssociationEndMembers[index].GetEntityType();
  1119. return code.CreateFullName(code.EscapeNamespace(GetObjectNamespace(entity.NamespaceName)), code.Escape(entity));
  1120. }
  1121.  
  1122. string GetObjectNamespace(string csdlNamespaceName)
  1123. {
  1124. string objectNamespace;
  1125. if (EdmToObjectNamespaceMap.TryGetValue(csdlNamespaceName, out objectNamespace))
  1126. {
  1127. return objectNamespace;
  1128. }
  1129.  
  1130. return csdlNamespaceName;
  1131. }
  1132.  
  1133. void UpdateObjectNamespaceMap(string objectNamespace)
  1134. {
  1135. if(objectNamespace != ModelNamespace && !EdmToObjectNamespaceMap.ContainsKey(ModelNamespace))
  1136. {
  1137. EdmToObjectNamespaceMap.Add(ModelNamespace, objectNamespace);
  1138. }
  1139. }
  1140.  
  1141. static string FixParameterName(string name, CodeGenerationTools code)
  1142. {
  1143. // Change any property that is 'id' (case insensitive) to 'ID'
  1144. // since 'iD' is a violation of FxCop rules.
  1145. if (StringComparer.OrdinalIgnoreCase.Equals(name, "id"))
  1146. {
  1147. // Return all lower case since it is an abbreviation, not an acronym.
  1148. return "id";
  1149. }
  1150. return code.CamelCase(name);
  1151. }
  1152.  
  1153. string BaseTypeName(EntityType entity, CodeGenerationTools code)
  1154. {
  1155. return entity.BaseType == null ? "EntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code);
  1156. }
  1157.  
  1158. bool IncludePropertyInFactoryMethod(StructuralType factoryType, EdmProperty edmProperty)
  1159. {
  1160. if (edmProperty.Nullable)
  1161. {
  1162. return false;
  1163. }
  1164.  
  1165. if (edmProperty.DefaultValue != null)
  1166. {
  1167. return false;
  1168. }
  1169.  
  1170. if ((Accessibility.ForReadOnlyProperty(edmProperty) != "public" && Accessibility.ForWriteOnlyProperty(edmProperty) != "public") ||
  1171. (factoryType != edmProperty.DeclaringType && Accessibility.ForWriteOnlyProperty(edmProperty) == "private")
  1172. )
  1173. {
  1174. // There is no public part to the property.
  1175. return false;
  1176. }
  1177.  
  1178. return true;
  1179. }
  1180.  
  1181.  
  1182. class FactoryMethodParameter
  1183. {
  1184. public EdmProperty Source;
  1185. public string RawParameterName;
  1186. public string ParameterName;
  1187. public string ParameterType;
  1188. public string ParameterComment;
  1189. public bool IsComplexType;
  1190.  
  1191. public static IEnumerable<FactoryMethodParameter> CreateParameters(IEnumerable<EdmProperty> properties, UniqueIdentifierService unique, Func<TypeUsage, CodeGenerationTools, string> multiSchemaEscape, CodeGenerationTools code)
  1192. {
  1193. List<FactoryMethodParameter> parameters = new List<FactoryMethodParameter>();
  1194. foreach (EdmProperty property in properties)
  1195. {
  1196. FactoryMethodParameter parameter = new FactoryMethodParameter();
  1197. parameter.Source = property;
  1198. parameter.IsComplexType = property.TypeUsage.EdmType is ComplexType;
  1199. parameter.RawParameterName = unique.AdjustIdentifier(FixParameterName(property.Name, code));
  1200. parameter.ParameterName = code.Escape(parameter.RawParameterName);
  1201. parameter.ParameterType = multiSchemaEscape(property.TypeUsage, code);
  1202. parameter.ParameterComment = String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_CommentFactoryMethodParam"), property.Name);
  1203. parameters.Add(parameter);
  1204. }
  1205.  
  1206. return parameters;
  1207. }
  1208. }
  1209.  
  1210. string DefaultSummaryComment{ get; set; }
  1211.  
  1212. string SummaryComment(MetadataItem item)
  1213. {
  1214. if (item.Documentation != null && item.Documentation.Summary != null)
  1215. {
  1216. return PrefixLinesOfMultilineComment(XMLCOMMENT_START + " ", XmlEntityize(item.Documentation.Summary));
  1217. }
  1218.  
  1219. if (DefaultSummaryComment != null)
  1220. {
  1221. return DefaultSummaryComment;
  1222. }
  1223.  
  1224. return string.Empty;
  1225. }
  1226.  
  1227. string LongDescriptionCommentElement(MetadataItem item, int indentLevel)
  1228. {
  1229. if (item.Documentation != null && !String.IsNullOrEmpty(item.Documentation.LongDescription))
  1230. {
  1231. string comment = Environment.NewLine;
  1232. string lineStart = CodeRegion.GetIndent(indentLevel) + XMLCOMMENT_START + " ";
  1233. comment += lineStart + "<LongDescription>" + Environment.NewLine;
  1234. comment += lineStart + PrefixLinesOfMultilineComment(lineStart, XmlEntityize(item.Documentation.LongDescription)) + Environment.NewLine;
  1235. comment += lineStart + "</LongDescription>";
  1236. return comment;
  1237. }
  1238. return string.Empty;
  1239. }
  1240.  
  1241. string PrefixLinesOfMultilineComment(string prefix, string comment)
  1242. {
  1243. return comment.Replace(Environment.NewLine, Environment.NewLine + prefix);
  1244. }
  1245.  
  1246. string ParameterComments(IEnumerable<Tuple<string, string>> parameters, int indentLevel)
  1247. {
  1248. System.Text.StringBuilder builder = new System.Text.StringBuilder();
  1249. foreach (Tuple<string, string> parameter in parameters)
  1250. {
  1251. builder.AppendLine();
  1252. builder.Append(CodeRegion.GetIndent(indentLevel));
  1253. builder.Append(XMLCOMMENT_START);
  1254. builder.Append(String.Format(CultureInfo.InvariantCulture, " <param name=\"{0}\">{1}</param>", parameter.Item1, parameter.Item2));
  1255. }
  1256. return builder.ToString();
  1257. }
  1258.  
  1259. string XmlEntityize(string text)
  1260. {
  1261. if (string.IsNullOrEmpty(text))
  1262. {
  1263. return string.Empty;
  1264. }
  1265.  
  1266. text = text.Replace("&","&amp;");
  1267. text = text.Replace("<","&lt;").Replace(">","&gt;");
  1268. string id = Guid.NewGuid().ToString();
  1269. text = text.Replace(Environment.NewLine, id);
  1270. text = text.Replace("\r", "&#xD;").Replace("\n","&#xA;");
  1271. text = text.Replace(id, Environment.NewLine);
  1272. return text.Replace("\'","&apos;").Replace("\"","&quot;");
  1273. }
  1274.  
  1275. const string XMLCOMMENT_START = "///";
  1276. IEnumerable<EdmProperty> GetProperties(StructuralType type)
  1277. {
  1278. if (type.BuiltInTypeKind == BuiltInTypeKind.EntityType)
  1279. {
  1280. return ((EntityType)type).Properties;
  1281. }
  1282. else
  1283. {
  1284. return ((ComplexType)type).Properties;
  1285. }
  1286. }
  1287.  
  1288. protected void VerifyGetterAndSetterAccessibilityCompatability(EdmMember member)
  1289. {
  1290. string rawGetterAccessibility = Accessibility.ForReadOnlyProperty(member);
  1291. string rawSetterAccessibility = Accessibility.ForWriteOnlyProperty(member);
  1292.  
  1293. if ((rawGetterAccessibility == "internal" && rawSetterAccessibility == "protected") ||
  1294. (rawGetterAccessibility == "protected" && rawSetterAccessibility == "internal"))
  1295.  
  1296. {
  1297. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6033", String.Format(CultureInfo.CurrentCulture,
  1298. GetResourceString("GeneratedPropertyAccessibilityConflict"),
  1299. member.Name, rawGetterAccessibility, rawSetterAccessibility)));
  1300. }
  1301. }
  1302.  
  1303. private void VerifyEntityTypeAndSetAccessibilityCompatability(EntitySet set)
  1304. {
  1305. string typeAccess = Accessibility.ForType(set.ElementType);
  1306. string setAccess = Accessibility.ForReadOnlyProperty(set);
  1307.  
  1308. if(typeAccess == "internal" && (setAccess == "public" || setAccess == "protected"))
  1309. {
  1310. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6036", String.Format(CultureInfo.CurrentCulture,
  1311. GetResourceString("EntityTypeAndSetAccessibilityConflict"),
  1312. set.ElementType.Name, typeAccess, set.Name, setAccess)));
  1313. }
  1314. }
  1315.  
  1316. ////////
  1317. //////// UniqueIdentifierService
  1318. ////////
  1319. sealed class UniqueIdentifierService
  1320. {
  1321. private readonly HashSet<string> _knownIdentifiers;
  1322.  
  1323. public UniqueIdentifierService()
  1324. {
  1325. _knownIdentifiers = new HashSet<string>(StringComparer.Ordinal);
  1326. }
  1327.  
  1328. /// <summary>
  1329. /// Makes the supplied identifier unique within the scope by adding
  1330. /// a suffix (1, 2, 3, ...), and returns the unique identifier.
  1331. /// </summary>
  1332. public string AdjustIdentifier(string identifier)
  1333. {
  1334. // find a unique name by adding suffix as necessary
  1335. var numberOfConflicts = 0;
  1336. var adjustedIdentifier = identifier;
  1337.  
  1338. while (!_knownIdentifiers.Add(adjustedIdentifier))
  1339. {
  1340. ++numberOfConflicts;
  1341. adjustedIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture);
  1342. }
  1343.  
  1344. return adjustedIdentifier;
  1345. }
  1346. }
  1347.  
  1348. #>
  1349.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty