<#@ template debug="true" hostSpecific="true" language="C#" #> <#@ output extension=".cs" #> <#@ assembly name="EnvDTE80" #> <#@ import namespace="System" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Diagnostics" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="EnvDTE80" #> <#@ import namespace="Microsoft.VisualStudio.TextTemplating"#> <#@ include file="EF.Utility.CS.ttinclude"#> <# // Set this flag to true to generate internal implementation classes for public entity interfaces var internalEntityClasses = false; var code = new CodeGenerationTools(this); var helper = new Helper(this, internalEntityClasses); var namespaceName = code.VsNamespaceSuggestion(); var contextClassName = System.IO.Path.GetFileNameWithoutExtension(this.Host.TemplateFile); WriteHeader(helper.GetExtraUsings().ToArray()); BeginNamespace(code, namespaceName); WriteContextClass(code, helper, contextClassName); EndNamespace(namespaceName); foreach(var i in helper.GetDecoratedInterfaces()) { WriteEntityClass(code, helper, i); } #> <#+ public void WriteHeader(params string[] extraUsings) { #> // ----------------------------------------------------------------------- // // This code was generated from a template. // // Changes to this file may cause incorrect behaviour and will be lost // if the code is regenerated. // //------------------------------------------------------------------------ using System; using System.Collections.Generic; using System.Linq; using BrightstarDB.Client; using BrightstarDB.EntityFramework; <#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#> <#+ } public void BeginNamespace(CodeGenerationTools code, string namespaceName) { CodeRegion region = new CodeRegion(this); if (!String.IsNullOrEmpty(namespaceName)) { #> namespace <#=code.EscapeNamespace(namespaceName) #> { <#+ PushIndent(CodeRegion.GetIndent(1)); } } public void EndNamespace(string namespaceName) { if (!String.IsNullOrEmpty(namespaceName)) { PopIndent(); #> } <#+ } } private void WriteContextClass(CodeGenerationTools code, Helper helper, string contextClassName) { #> public partial class <#=code.Escape(contextClassName) #> : BrightstarEntityContext { static <#= code.Escape(contextClassName) #>() { InitializeEntityMappingStore(); } /// /// Initialize the internal cache of entity attribute information. /// /// /// This method is normally invoked from the static constructor for the generated context class. /// It is provided as a public static method to enable the use of the cached entity attribute /// information without the need to construct a context (typically in test code). /// In normal application code you should never need to explicitly call this method. /// public static void InitializeEntityMappingStore() { var provider = new ReflectionMappingProvider(); <#+ foreach(var i in helper.GetDecoratedInterfaces()) { #> provider.AddMappingsForType(EntityMappingStore.Instance, typeof(<#=i.InterfaceFullName#>)); EntityMappingStore.Instance.SetImplMapping<<#=i.InterfaceFullName#>, <#=code.CreateFullName(i.InterfaceNamespaceName, i.ClassName)#>>(); <#+ } #> } /// /// Initialize a new entity context using the specified BrightstarDB /// Data Object Store connection /// /// The connection to the BrightstarDB Data Object Store that will provide the entity objects public <#= code.Escape(contextClassName) #>(IDataObjectStore dataObjectStore) : base(dataObjectStore) { InitializeContext(); } /// /// Initialize a new entity context using the specified Brightstar connection string /// /// The connection to be used to connect to an existing BrightstarDB store /// OPTIONAL: If set to true optmistic locking will be applied to all entity updates /// OPTIONAL: The URI identifier of the graph to be updated with any new triples created by operations on the store. If /// not defined, the default graph in the store will be updated. /// OPTIONAL: The URI identifiers of the graphs that will be queried to retrieve entities and their properties. /// If not defined, all graphs in the store will be queried. /// OPTIONAL: The URI identifier of the graph that contains version number statements for entities. /// If not defined, the will be used. public <#= code.Escape(contextClassName) #>( string connectionString, bool? enableOptimisticLocking=null, string updateGraphUri = null, IEnumerable datasetGraphUris = null, string versionGraphUri = null ) : base(connectionString, enableOptimisticLocking, updateGraphUri, datasetGraphUris, versionGraphUri) { InitializeContext(); } /// /// Initialize a new entity context using the specified Brightstar /// connection string retrieved from the configuration. /// public <#= code.Escape(contextClassName) #>() : base() { InitializeContext(); } /// /// Initialize a new entity context using the specified Brightstar /// connection string retrieved from the configuration and the // specified target graphs /// /// The URI identifier of the graph to be updated with any new triples created by operations on the store. If /// set to null, the default graph in the store will be updated. /// The URI identifiers of the graphs that will be queried to retrieve entities and their properties. /// If set to null, all graphs in the store will be queried. /// The URI identifier of the graph that contains version number statements for entities. /// If set to null, the value of will be used. public <#= code.Escape(contextClassName) #>( string updateGraphUri, IEnumerable datasetGraphUris, string versionGraphUri ) : base(updateGraphUri:updateGraphUri, datasetGraphUris:datasetGraphUris, versionGraphUri:versionGraphUri) { InitializeContext(); } private void InitializeContext() { <#+ foreach(var i in helper.GetDecoratedInterfaces()) { #> <#= code.Escape(i.PluralizedName) #> = new BrightstarEntitySet<<#=i.InterfaceFullName#>>(this); <#+ } #> } <#+ foreach(var i in helper.GetDecoratedInterfaces()) { #> <#=i.GetEntitySetAccessLevel(helper)#> IEntitySet<<#=i.InterfaceFullName#>> <#= code.Escape(i.PluralizedName) #> { get; private set; } <#+ } #> public IEntitySet EntitySet() where T : class { var itemType = typeof(T); <#+ foreach(var i in helper.GetDecoratedInterfaces()) { #> if (typeof(T).Equals(typeof(<#=i.InterfaceFullName#>))) { return (IEntitySet)this.<#= code.Escape(i.PluralizedName) #>; } <#+ } #> throw new InvalidOperationException(typeof(T).FullName + " is not a recognized entity interface type."); } } // end class <#=code.Escape(contextClassName)#> <#+ } private void WriteEntityClass(CodeGenerationTools code, Helper helper, ResourceInterface iface) { BeginNamespace(code, iface.InterfaceNamespaceName); var identityProperty = iface.IdentityProperty; WriteClassAttributes(code, helper, iface); #> <#= code.SpaceAfter(iface.GetEntitySetAccessLevel(helper))#>partial class <#= iface.ClassName #> : BrightstarEntityObject, <#= iface.InterfaceName #> { public <#= iface.ClassName#>(BrightstarEntityContext context, BrightstarDB.Client.IDataObject dataObject) : base(context, dataObject) { } public <#= iface.ClassName#>(BrightstarEntityContext context) : base(context, typeof(<#= iface.ClassName #>)) { } public <#= iface.ClassName#>() : base() { } <#+ if (identityProperty != null) { ValidateIdentityProperty(identityProperty); #> public <#= ((CodeProperty)identityProperty).Type.AsFullName #> <#= identityProperty.Name #> { get {return GetKey(); } set { SetKey(value); } } <#+ } WriteInterfaceImplementation(code, helper, iface); foreach(var b in iface.AllInterfaces){ WriteInterfaceImplementation(code, helper, b); } #> } <#+ EndNamespace(iface.InterfaceNamespaceName); } private void WriteInterfaceImplementation(CodeGenerationTools code, Helper helper, ResourceInterface iface) {#> #region Implementation of <#= iface.InterfaceFullName #> <#+ foreach(var p in iface.Properties) { if (IsIgnoredProperty(p)) { continue; } if (!p.Equals(iface.IdentityProperty)) { bool isCollectionProperty; if (ValidateProperty(p, helper, out isCollectionProperty)) { WritePropertyAttributes(code, helper, p); if (isCollectionProperty) { string generic, t; Helper.TryParseGenericTypeName(p.Type.AsFullName, out generic, out t); generic = Helper.GetEntityGeneric(generic); if (generic == null) { this.Error(String.Format("There is no known mapping for the generic type {0} on the property {1} of type {2}", generic, p.Name, p.Type.AsFullName)); } else { #> public <#= generic#><<#=t#>> <#= p.Name #> { <#+ if (helper.GetDecoratedInterfaces().Any(x=>x.InterfaceFullName.Equals(t))) { #> get { return GetRelatedObjects<<#=t#>>(<#= code.CreateLiteral(p.Name) #>); } set { if (value == null) throw new ArgumentNullException("value"); SetRelatedObjects(<#= code.CreateLiteral(p.Name)#>, value); } <#+ } else { #> get { return GetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name) #>); } set { if (value == null) throw new ArgumentNullException("value"); SetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name)#>, value); } <#+ } #> } <#+ } } else { var itemType = GetPropertyTypeName(p.Type); #> public <#= itemType #> <#= p.Name #> { <#+ PushIndent(CodeRegion.GetIndent(2)); if (IsValidLiteralType(helper, p.Type)) { #> get { return GetRelatedProperty<<#= itemType #>>(<#=code.CreateLiteral(p.Name)#>); } set { SetRelatedProperty(<#=code.CreateLiteral(p.Name)#>, value); } <#+ } else { if (p.Getter != null) WriteSingleGetter(code, p); if (p.Setter != null) WriteSingleSetter(code, p); } PopIndent(); #> } <#+ } } } } #> #endregion <#+ } private void WriteCustomAttribute(Helper helper, CodeAttribute attr) { if (attr.FullName.Equals("BrightstarDB.EntityFramework.ClassAttributeAttribute")) { var e = attr.Children.GetEnumerator(); if (e.MoveNext()) { var classAttributeArg = e.Current as EnvDTE80.CodeAttributeArgument; if (classAttributeArg != null) { #><#=helper.Unquote(classAttributeArg.Value)#><#+ } } } if (attr.FullName.StartsWith("BrightstarDB.EntityFramework")) { return; } #> [<#= attr.FullName#><#+ var childEnumerator = attr.Children.GetEnumerator(); if (childEnumerator.MoveNext()) { bool keepGoing = true; #>(<#+ while (keepGoing) { if (childEnumerator.Current is EnvDTE80.CodeAttributeArgument) { var arg = childEnumerator.Current as EnvDTE80.CodeAttributeArgument; if (!String.IsNullOrEmpty(arg.Name)) { #><#=arg.Name#>=<#=arg.Value#><#+ } else { #><#=arg.Value#><#+ } keepGoing = childEnumerator.MoveNext(); if (keepGoing) { #>, <#+ } } } #>)<#+ } #>]<#+ } private void WriteClassAttributes(CodeGenerationTools code, Helper helper, ResourceInterface iface) { foreach(var x in iface.Interface.Attributes) { if (x is CodeAttribute) { WriteCustomAttribute(helper, x as CodeAttribute); } } } private void WritePropertyAttributes(CodeGenerationTools code, Helper helper, CodeProperty property) { foreach(var x in property.Attributes) { if (x is CodeAttribute) { var attr = x as CodeAttribute; WriteCustomAttribute(helper, attr); } } } private bool IsValidLiteralType(Helper helper, CodeTypeRef t) { if (Constants.BasicTypes.Contains(t.AsFullName) || IsByteArray(t) || t.CodeType.IsDerivedFrom["System.Enum"]) { return true; } string genericName, typeName; if (Helper.TryParseGenericTypeName(t.AsFullName, out genericName, out typeName) && genericName.Equals("System.Nullable") && (helper.GetEnums().Any(e=>e.FullName.Equals(typeName)) || Helper.IsExternalEnum(typeName)) ) { return true; } return false; } private bool IsByteArray(CodeTypeRef t) { return t.TypeKind == vsCMTypeRef.vsCMTypeRefArray && t.ElementType.AsFullName == "System.Byte"; } private void WriteCollectionGetter(CodeGenerationTools code, CodeProperty property, string itemType) { if (Constants.BasicTypes.Contains(itemType)) { #> get { return GetRelatedProperties<<#= itemType #>>(<#=code.CreateLiteral(property.Name) #>); } <#+ } else { #> get { return GetRelatedObjects<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>); } <#+ } } private void WriteCollectionSetter(CodeGenerationTools code, CodeProperty property, string itemType) { if (Constants.BasicTypes.Contains(itemType)) { #> set { SetRelatedProperties(<#= code.CreateLiteral(property.Name) #>, value); } <#+ } else { #> set { SetRelatedObjects(<#= code.CreateLiteral(property.Name) #>, value ); } <#+ } } private void WriteSingleGetter(CodeGenerationTools code, CodeProperty property) { var itemType = property.Type.AsFullName; #> get { return GetRelatedObject<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>); } <#+ } private void WriteSingleSetter(CodeGenerationTools code, CodeProperty property) { var itemType = property.Type.AsFullName; #> set { SetRelatedObject<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>, value); } <#+ } private string GetPropertyTypeName(CodeTypeRef propertyType) { if (propertyType.TypeKind == vsCMTypeRef.vsCMTypeRefArray) { return propertyType.ElementType.AsFullName + "[]"; } else { return propertyType.AsFullName; } } private void ValidateIdentityProperty(CodeProperty property) { if (!property.Type.AsFullName.Equals("System.String")) { Error(String.Format("The property '{0}' must be of type String to be used as the identity property for an entity. If this property is intended to be the identity property for the entity please change its type to String. If it is not intended to be the identity property, either rename this property or create an identity property and decorate it with the [{1}] attribute.", property.FullName, Constants.IdentityAttributeShortName)); } if (property.Setter != null) { Error(String.Format("The property '{0}' must not have a setter to be used as the identity property for an entity. If this property is intended to be the identity property for the entity please remove the setter. If it is not intended to be the identity property, either rename this property or create an identity propertyn and decorate it with the [{1}] attribute.", property.FullName, Constants.IdentityAttributeShortName)); } } private bool IsIgnoredProperty(CodeProperty property) { var ignore = property.Attributes.OfType().FirstOrDefault( attr => attr.FullName.Equals(Constants.IgnorePropertyAttributeName)); return ignore != null; } private bool ValidateProperty(CodeProperty property, Helper helper, out bool isCollection) { var propertyTypeName = property.Type.AsFullName; isCollection = false; bool isValid = false; if (IsValidLiteralType(helper, property.Type) || helper.GetDecoratedInterfaces().Any(i=>i.InterfaceFullName.Equals(propertyTypeName))) { isValid = true; } else { string generic, t; if (Helper.TryParseGenericTypeName(propertyTypeName, out generic, out t)) { if (Constants.CollectionTypes.Contains(generic) && (Constants.BasicTypes.Contains(t) || helper.GetDecoratedInterfaces().Any(i=>i.InterfaceFullName.Equals(t)))) { isCollection = true; isValid = true; propertyTypeName = t; } } } if (!isValid) { Error("Invalid property: " + property.FullName + " - the property type " + propertyTypeName + " is not supported by Entity Framework."); isCollection = false; return false; } var inversePropertyAttr = property.Attributes.OfType().FirstOrDefault( attr => attr.FullName.Equals(Constants.InversePropertyAttributeName)); if (inversePropertyAttr != null) { var arg = inversePropertyAttr.Children.OfType().FirstOrDefault(); var inversePropertyName = arg.Value.Trim('\"'); var targetInterface = helper.GetDecoratedInterfaces().FirstOrDefault(i=>i.InterfaceFullName.Equals(propertyTypeName)); if (targetInterface == null) { this.Error("Invalid InverseProperty attribute on property " + property.Name + ". The property type " + propertyTypeName + " must be marked as an Entity."); return false; } var targetProperty = targetInterface.Properties.FirstOrDefault(p=>p.Name.Equals(inversePropertyName)); if (targetProperty == null) { this.Error("Invalid InverseProperty attribute on property " + property.Name + ". A property named '" + inversePropertyName + "' cannot be found on the target interface type '" + targetInterface.InterfaceFullName + "'."); return false; } } return true; } static class Constants { public const string IdentityAttributeName = "BrightstarDB.EntityFramework.IdentifierAttribute"; public const string IdentityAttributeShortName = "Identifier"; public const string EntityAttributeName = "BrightstarDB.EntityFramework.EntityAttribute"; public const string InversePropertyAttributeName = "BrightstarDB.EntityFramework.InversePropertyAttribute"; public const string IgnorePropertyAttributeName = "BrightstarDB.EntityFramework.IgnoreAttribute"; /// /// The property types that are supported entity property types /// public static readonly List BasicTypes = new List { "System.Boolean", "System.Int16", "System.Int64", "System.Int32", "System.UInt16", "System.UInt32", "System.UInt64", "System.String", "System.DateTime", "System.Decimal", "System.Double", "System.Single", "System.Uri", "System.Byte", "System.Char", "System.SByte", "System.Guid", "BrightstarDB.Rdf.PlainLiteral", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", "System.Nullable", }; /// /// The generic collection types that are supported entity collection property types /// public static readonly List CollectionTypes = new List { "System.Collections.Generic.ISet", "System.Collections.Generic.ICollection", }; public static readonly List CoreImports = new List { "System", "System.Collections.Generic", "System.Linq", "BrightstarDB.Client", "BrightstarDB.EntityFramework" }; } class Helper { private DTE _dte; public static TextTransformation _transformation; private ProjectItem _templateProjectItem; private Project _project; private vsCMAccess _defaultEntityClassAccess; public Helper(TextTransformation transformation, bool internalEntityClasses) { _transformation = transformation; _templateProjectItem = DTE.Solution.FindProjectItem(Host.TemplateFile); _project = _templateProjectItem.ContainingProject; _defaultEntityClassAccess = this.GetDefaultEntityClassAccess(internalEntityClasses); } public ITextTemplatingEngineHost Host { get { return _transformation.GetType().GetProperty("Host").GetValue(_transformation, null) as ITextTemplatingEngineHost; } } public DTE DTE { get { if (_dte == null) { IServiceProvider hostServiceProvider = (IServiceProvider)Host; _dte = hostServiceProvider.GetService(typeof(DTE)) as DTE; } return _dte; } } public IEnumerable GetInterfaces() { foreach(var pi in GetCodeProjectItems()) { foreach(CodeElement ce in GetInterfaces(pi.FileCodeModel.CodeElements)) { yield return ce; } } } public IEnumerable GetDecoratedInterfaces() { return GetCodeProjectItems().SelectMany(pi=>GetDecoratedInterfaces(pi.FileCodeModel.CodeElements)).Select(x=>new ResourceInterface(x)); } /// /// Returns an enumeration of all distinct using statements contained /// in the files that define BrightstarDB Entity Framework entity interfaces /// public IEnumerable GetExtraUsings() { return GetCodeProjectItems() .Where(pi=>GetDecoratedInterfaces(pi.FileCodeModel.CodeElements).Any()) .SelectMany(pi=>pi.FileCodeModel.CodeElements.OfType().Select(ce=>ce.Namespace)) .Distinct().Except(Constants.CoreImports); } public vsCMAccess DefaultEntityClassAccessibilty { get { return _defaultEntityClassAccess; } } /// /// Returns an enumeration over all the enums types defined in the project /// /// public IEnumerable GetEnums() { foreach(var pi in GetCodeProjectItems()) { foreach(CodeElement ce in GetEnums(pi.FileCodeModel.CodeElements)) { yield return (CodeEnum)ce; } } } /// /// Pass-through write operation to allow this class to contain template output /// /// public void Write(string text) { _transformation.Write(text); } /// /// Pass-through write operation to allow this class to contain template output /// /// public void Write(string msg, object[] args) { _transformation.Write(msg, args); } public static IEnumerable GetDecoratedInterfaces(CodeElements container) { return GetInterfaces(container).Where(i=>i.Children.OfType().Any(c=>c.Kind == vsCMElement.vsCMElementAttribute && c.FullName.Equals(Constants.EntityAttributeName))); } public static IEnumerable GetInterfaces(CodeElements container) { foreach(CodeElement ce in container) { if (ce.Kind == vsCMElement.vsCMElementInterface) { yield return ce; } else { foreach(var child in GetInterfaces(ce.Children)) { yield return child; } } } } public static IEnumerable GetEnums(CodeElements container) { foreach(CodeElement ce in container) { if (ce.Kind == vsCMElement.vsCMElementEnum) { yield return ce; } else { foreach(var child in GetEnums(ce.Children)) { yield return child; } } } } public static bool IsExternalEnum(string typeName){ try { return Type.GetType(typeName, true, false).IsEnum; } catch(Exception){ return false; } } public static bool TryParseGenericTypeName(string genericTypeName, out string generic, out string t) { var regex = new System.Text.RegularExpressions.Regex(@"^([a-zA-Z0-9\.]+)<([^>]+)>$"); var match = regex.Match(genericTypeName); if (match.Success) { generic=match.Groups[1].Value; t = match.Groups[2].Value; return true; } else { generic = t = null; return false; } } public static string GetEntityGeneric(string genericTypeName) { if (genericTypeName.Equals("System.Collections.Generic.ICollection")) { return "System.Collections.Generic.ICollection"; } return null; } public IEnumerable GetCodeProjectItems() { foreach(var pi in GetCodeProjectItems(_project.ProjectItems)) { yield return pi; } } public string Unquote(string quotedString) { if(quotedString.StartsWith("\"")) { return quotedString.Trim('\"').Replace("\\\"", "\""); } else if (quotedString.StartsWith("@\"")) { return quotedString.TrimStart('@','\"').TrimEnd('\"'); } else { return quotedString; } } private IEnumerable GetCodeProjectItems(ProjectItems projectItems) { foreach(ProjectItem pi in projectItems) { if (pi.Equals(_templateProjectItem)) { continue; } if (pi.FileCodeModel != null) { yield return pi; } if (pi.ProjectItems != null) { foreach(var childItem in GetCodeProjectItems(pi.ProjectItems)) { yield return childItem; } } } } private vsCMAccess GetDefaultEntityClassAccess(bool internalEntityClasses) { return internalEntityClasses ? vsCMAccess.vsCMAccessProject : vsCMAccess.vsCMAccessDefault; } } class ResourceInterface { private CodeInterface _interfaceCE; private CodeProperty _identityProperty; private string _className; public ResourceInterface(CodeInterface interfaceCE){ _interfaceCE = interfaceCE; _identityProperty = (CodeProperty)FindIdentityProperty(); } public ResourceInterface(CodeElement rootElement) { _interfaceCE = ((CodeInterface)rootElement); _identityProperty = (CodeProperty)FindIdentityProperty(); } public IEnumerable Properties { get { return _interfaceCE.Children .OfType() .Where(c=>c.Kind == vsCMElement.vsCMElementProperty) .Select(c=>(CodeProperty)c); } } public CodeInterface Interface { get { return _interfaceCE; } } public IEnumerable BaseInterfaces { get { foreach(var baseInterface in _interfaceCE.Bases.OfType().Where(HasEntityAttribute)) { yield return new ResourceInterface(baseInterface); } } } private bool HasEntityAttribute(CodeInterface iface) { try { return iface.Children.OfType().Any(c=>c.Kind == vsCMElement.vsCMElementAttribute && c.FullName.Equals(Constants.EntityAttributeName)); } catch { return false; } } public void GetAllInterfaces(List interfaces) { foreach (var ri in BaseInterfaces) { if (!interfaces.Contains(ri)) { interfaces.Add(ri); } ri.GetAllInterfaces(interfaces); } } public IEnumerable AllInterfaces { get { var resourceInterfaces = new List(); GetAllInterfaces(resourceInterfaces); return resourceInterfaces; } } private CodeProperty FindIdentityProperty() { // Find the identity property on the interface (if any) var ret = Properties.Where( c=> c.Attributes.OfType().Any( attr => attr.FullName.Equals(Constants.IdentityAttributeName))).FirstOrDefault(); if (ret == null) ret = Properties.Where( c=> (c.Name.Equals(ClassName+"Id") || c.Name.Equals(ClassName+"ID"))).FirstOrDefault(); if (ret == null) { ret = Properties.Where( c=> (c.Name.Equals("Id") || c.Name.Equals("ID"))).FirstOrDefault(); } // if there is no indication on this class of an id property then check the interfaces we inherit from if (ret == null) { foreach (var bi in AllInterfaces){ ret = bi.FindIdentityProperty(); if (ret != null) return ret; } } else { foreach (var bi in AllInterfaces){ var aret = bi.FindIdentityProperty(); if (aret != null && (!aret.Name.Equals(ret.Name))) { Helper._transformation.Error("Invalid identity property " + ret.Name + " on " + _interfaceCE.Name + " it differs from ancestor id " + aret.Name + " on " + bi.InterfaceName); } } } return ret; } public void ValidateIdentityProperty(CodeProperty identityProperty){ foreach (var bi in AllInterfaces){ var aret = bi.FindIdentityProperty(); if (aret != null && (aret.Name != identityProperty.Name)) { throw new Exception("Invalid identity property. It differs from ancestor identity."); } } } public string ClassName { get { if (_className == null) { if (_interfaceCE.Name.StartsWith("I")) { _className = _interfaceCE.Name.Substring(1); } else { _className = _interfaceCE.Name + "Impl"; } } return _className; } } public string InterfaceName { get { return _interfaceCE.Name; } } public string InterfaceFullName { get { return _interfaceCE.FullName; } } public string InterfaceNamespaceName { get { return _interfaceCE.Namespace.FullName; } } public CodeProperty IdentityProperty { get {return _identityProperty; } } public string PluralizedName { get { return Pluralize(_interfaceCE.Name.StartsWith("I") ? _interfaceCE.Name.Substring(1) : _interfaceCE.Name); } } public string Pluralize(string name) { if (name.EndsWith("y")) { return name.Substring(0, name.Length - 1) + "ies"; } return name + "s"; } public string GetEntitySetAccessLevel(Helper helper) { var defaultAccess = helper.DefaultEntityClassAccessibilty; switch (_interfaceCE.Access) { case vsCMAccess.vsCMAccessPublic : // If the interface is public, the class will be public *unless* overridden by the EF-specific assembly-level attribute return defaultAccess == vsCMAccess.vsCMAccessProject ? "internal" : "public"; case vsCMAccess.vsCMAccessPrivate : // A private interface must be implemented by a private class return "private"; case vsCMAccess.vsCMAccessProject : case vsCMAccess.vsCMAccessAssemblyOrFamily: // Internal or Internal protected interfaces must be implemented by an internal class return "internal"; default : // We shouldn't hit this return "private"; } } } #>