Skip to content

Commit

Permalink
Add basic support for Entity Framework Code First
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ganss committed Jul 9, 2015
1 parent eb6acab commit 1a61887
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
11 changes: 7 additions & 4 deletions XmlSchemaClassGenerator.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static void Main(string[] args)
var pclCompatible = false;
var enableDataBinding = false;
var emitOrder = false;
var entityFramework = false;

var options = new OptionSet {
{ "h|help", "show this message and exit", v => showHelp = v != null },
Expand All @@ -35,7 +36,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
{ "o|output=", "the {FOLDER} to write the resulting .cs files to", v => outputFolder = v },
{ "i|integer=", @"map xs:integer and derived types to {TYPE} instead of string
{TYPE} can be i[nt], l[ong], or d[ecimal].", v => {
switch (v)
switch (v)
{
case "i":
case "int":
Expand All @@ -51,12 +52,13 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
break;
}
} },
{ "edb|enable-data-binding", "Enable INotifyPropertyChanged data binding", v => enableDataBinding = v != null },
{ "order", "Emit order for all class members stored as XML element", v => emitOrder = v != null },
{ "pcl", "PCL compatible output", v => pclCompatible = v != null },
{ "e|edb|enable-data-binding", "Enable INotifyPropertyChanged data binding", v => enableDataBinding = v != null },
{ "r|order", "Emit order for all class members stored as XML element", v => emitOrder = v != null },
{ "c|pcl", "PCL compatible output", v => pclCompatible = v != null },
{ "p|prefix=", "the {PREFIX} to prepend to auto-generated namespace names", v => namespacePrefix = v },
{ "v|verbose", "print generated file names on stdout", v => verbose = v != null },
{ "0|nullable", "generate nullable adapter properties for optional elements/attributes w/o default values", v => nullables = v != null },
{ "f|ef", "generate Entity Framework Code First compatible classes", v => entityFramework = v != null },
};

var files = options.Parse(args);
Expand Down Expand Up @@ -89,6 +91,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
EnableDataBinding = enableDataBinding,
EmitOrder = emitOrder,
IntegerDataType = integerType,
EntityFramework = entityFramework
};

if (pclCompatible)
Expand Down
1 change: 1 addition & 0 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ private Assembly Compile(string name, string pattern)
IntegerDataType = typeof(int),
DataAnnotationMode = DataAnnotationMode.Partial,
GenerateDesignerCategoryAttribute = false,
EntityFramework = true
};

var files = Glob.Glob.ExpandNames(pattern);
Expand Down
6 changes: 6 additions & 0 deletions XmlSchemaClassGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ public Type IntegerDataType
set { _configuration.IntegerDataType = value; }
}

public bool EntityFramework
{
get { return _configuration.EntityFramework; }
set { _configuration.EntityFramework = value; }
}

private readonly XmlSchemaSet Set = new XmlSchemaSet();
private Dictionary<XmlQualifiedName, XmlSchemaAttributeGroup> AttributeGroups;
private readonly Dictionary<NamespaceKey, NamespaceModel> Namespaces = new Dictionary<NamespaceKey, NamespaceModel>();
Expand Down
4 changes: 4 additions & 0 deletions XmlSchemaClassGenerator/GeneratorConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ public GeneratorConfiguration()
/// Default data type for numeric fields
/// </summary>
public Type IntegerDataType { get; set; }
/// <summary>
/// Generate Entity Framework Code First compatible classes
/// </summary>
public bool EntityFramework { get; set; }

/// <summary>
/// Provides a fast and safe way to write to the Log
Expand Down
46 changes: 46 additions & 0 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -260,6 +261,28 @@ public override CodeTypeDeclaration Generate()
if (EnableDataBinding)
classDeclaration.BaseTypes.Add(new CodeTypeReference("INotifyPropertyChanged"));

if (Configuration.EntityFramework && (BaseClass == null || !(BaseClass is ClassModel)))
{
// generate key
var keyProperty = Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == "id")
?? Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == (Name.ToLowerInvariant() + "id"));

if (keyProperty == null)
{
keyProperty = new PropertyModel(Configuration)
{
Name = "Id",
Type = new SimpleModel(Configuration) { ValueType = typeof(long) },
OwningType = this,
Documentation = { new DocumentationModel { Language = "en", Text = "Gets or sets a value uniquely identifying this entity." },
new DocumentationModel { Language = "de", Text = "Ruft einen Wert ab, der diese Entität eindeutig identifiziert, oder legt diesen fest." } }
};
Properties.Insert(0, keyProperty);
}

keyProperty.IsKey = true;
}

foreach (var property in Properties)
property.AddMembersTo(classDeclaration, EnableDataBinding);

Expand Down Expand Up @@ -347,6 +370,7 @@ public class PropertyModel
public XmlQualifiedName XmlSchemaName { get; set; }
public bool IsAny { get; set; }
public int? Order { get; set; }
public bool IsKey { get; set; }
public GeneratorConfiguration Configuration { get; private set; }

public PropertyModel(GeneratorConfiguration configuration)
Expand Down Expand Up @@ -465,6 +489,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
Attributes = MemberAttributes.Private
};
var ignoreAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlIgnoreAttribute)));
var notMappedAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(NotMappedAttribute)));
backingField.CustomAttributes.Add(ignoreAttribute);

if (requiresBackingField)
Expand Down Expand Up @@ -534,6 +559,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
var specifiedName = Configuration.GenerateNullables ? Name + "Value" : Name;
var specifiedMember = new CodeMemberField(typeof(bool), specifiedName + "Specified { get; set; }");
specifiedMember.CustomAttributes.Add(ignoreAttribute);
if (Configuration.EntityFramework && Configuration.GenerateNullables) specifiedMember.CustomAttributes.Add(notMappedAttribute);
specifiedMember.Attributes = MemberAttributes.Public;
var specifiedDocs = new[] { new DocumentationModel { Language = "en", Text = string.Format("Gets or sets a value indicating whether the {0} property is specified.", Name) },
new DocumentationModel { Language = "de", Text = string.Format("Ruft einen Wert ab, der angibt, ob die {0}-Eigenschaft spezifiziert ist, oder legt diesen fest.", Name) } };
Expand Down Expand Up @@ -607,6 +633,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
editorBrowsableAttribute.Arguments.Add(new CodeAttributeArgument(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(EditorBrowsableState)), "Never")));
specifiedMember.CustomAttributes.Add(editorBrowsableAttribute);
member.CustomAttributes.Add(editorBrowsableAttribute);
if (Configuration.EntityFramework) member.CustomAttributes.Add(notMappedAttribute);
}
}
else if ((IsCollection || isArray) && IsNullable && !IsAttribute)
Expand All @@ -619,6 +646,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
HasGet = true,
};
specifiedProperty.CustomAttributes.Add(ignoreAttribute);
if (Configuration.EntityFramework) specifiedProperty.CustomAttributes.Add(notMappedAttribute);
specifiedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;

var listReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name);
Expand Down Expand Up @@ -665,11 +693,29 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
propertyAttribute.Arguments.Cast<CodeAttributeArgument>().Where(x => !string.Equals(x.Name, "Order", StringComparison.Ordinal)).ToArray());
member.CustomAttributes.Add(arrayItemAttribute);
}

if (IsKey)
{
var keyAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(KeyAttribute)));
member.CustomAttributes.Add(keyAttribute);
}

if (IsAny && Configuration.EntityFramework)
{
member.CustomAttributes.Add(notMappedAttribute);
}
}

private CodeAttributeDeclaration GetAttribute(bool isArray)
{
CodeAttributeDeclaration attribute;

if (IsKey && XmlSchemaName == null)
{
attribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlIgnoreAttribute)));
return attribute;
}

if (IsAttribute)
{
if (IsAny)
Expand Down

0 comments on commit 1a61887

Please sign in to comment.