使用 CodeDOM 生成字段而不是属性
Generate fields instead of properties with CodeDOM
我使用 CodeDOM 从 XSD-schema-file 创建了一些代码:
XmlSchemaImporter importer = new XmlSchemaImporter(schemas);
CodeNamespace code = new CodeNamespace(targetNamespace);
XmlCodeExporter exporter = new XmlCodeExporter(code);
foreach (XmlSchemaElement element in schema.Elements.Values)
{
XmlTypeMapping mapping = importer.ImportTypeMapping(element.QualifiedName);
exporter.ExportTypeMapping(mapping);
}
现在在我的 post-processing 中,我意识到这段代码将生成如下属性:
bool prop1Field;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public bool Prop1
{
get
{
return prop1Field;
}
set
{
prop1Field = value;
}
}
但我希望生成器只生成字段。有没有办法做到这一点?我知道 xsd.exe
在使用 /f
参数时也会生成字段。
编辑:之后我想用自动属性替换它们。要使用当前方法做到这一点,我必须从 属性 中删除支持字段及其在生成的代码中的所有出现。但是,如果 CodeDOM 首先生成一个 public
字段,我所要做的就是删除该字段,使用 CodeSnippedTypeMember
创建一个同名的新 属性,如 [=16] 所示=].因此,我不需要搜索代码以查找私有支持字段的出现,并通过调用 属性.
来替换它们
不,没有设置允许这样做的选项,因为如果您的属性是字段或 属性(假设我们不使用反射),那么使用代码并不重要,并且public 字段被认为是不好的做法。
无论如何,我找到了一种方法来实现此目的,方法是将 属性 的所有注释和属性复制到私有支持字段并使该字段成为 public。但是请记住,这样做主要是一个糟糕的设计理念。
public void Process(CodeNamespace code, XmlSchema schema)
{
foreach (var type in code.Types.Cast<CodeTypeDeclaration>().Where(x => !x.IsEnum))
{
var result = new List<CodeMemberField>();
var properties = type.Members.OfType<CodeMemberProperty>().ToList();
foreach (var property in properties)
{
ReplacePropertyByField(type, property);
}
}
}
private static void ReplacePropertyByField(CodeTypeDeclaration type, CodeMemberProperty property)
{
var backingField = GetBackingField(property, type);
backingField.Comments.AddRange(property.Comments);
backingField.Attributes = property.Attributes;
backingField.CustomAttributes = property.CustomAttributes;
backingField.Name = property.Name;
type.Members.Remove(property);
}
private static CodeMemberField GetBackingField(CodeMemberProperty property, CodeTypeDeclaration type)
{
var getterExpression = ((CodeMethodReturnStatement)property.GetStatements[0]).Expression;
var backingFieldName = ((CodeFieldReferenceExpression)getterExpression).FieldName;
return type.Members.OfType<CodeMemberField>().Single(x => x.Name == backingFieldName);
}
我使用 CodeDOM 从 XSD-schema-file 创建了一些代码:
XmlSchemaImporter importer = new XmlSchemaImporter(schemas);
CodeNamespace code = new CodeNamespace(targetNamespace);
XmlCodeExporter exporter = new XmlCodeExporter(code);
foreach (XmlSchemaElement element in schema.Elements.Values)
{
XmlTypeMapping mapping = importer.ImportTypeMapping(element.QualifiedName);
exporter.ExportTypeMapping(mapping);
}
现在在我的 post-processing 中,我意识到这段代码将生成如下属性:
bool prop1Field;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public bool Prop1
{
get
{
return prop1Field;
}
set
{
prop1Field = value;
}
}
但我希望生成器只生成字段。有没有办法做到这一点?我知道 xsd.exe
在使用 /f
参数时也会生成字段。
编辑:之后我想用自动属性替换它们。要使用当前方法做到这一点,我必须从 属性 中删除支持字段及其在生成的代码中的所有出现。但是,如果 CodeDOM 首先生成一个 public
字段,我所要做的就是删除该字段,使用 CodeSnippedTypeMember
创建一个同名的新 属性,如 [=16] 所示=].因此,我不需要搜索代码以查找私有支持字段的出现,并通过调用 属性.
不,没有设置允许这样做的选项,因为如果您的属性是字段或 属性(假设我们不使用反射),那么使用代码并不重要,并且public 字段被认为是不好的做法。
无论如何,我找到了一种方法来实现此目的,方法是将 属性 的所有注释和属性复制到私有支持字段并使该字段成为 public。但是请记住,这样做主要是一个糟糕的设计理念。
public void Process(CodeNamespace code, XmlSchema schema)
{
foreach (var type in code.Types.Cast<CodeTypeDeclaration>().Where(x => !x.IsEnum))
{
var result = new List<CodeMemberField>();
var properties = type.Members.OfType<CodeMemberProperty>().ToList();
foreach (var property in properties)
{
ReplacePropertyByField(type, property);
}
}
}
private static void ReplacePropertyByField(CodeTypeDeclaration type, CodeMemberProperty property)
{
var backingField = GetBackingField(property, type);
backingField.Comments.AddRange(property.Comments);
backingField.Attributes = property.Attributes;
backingField.CustomAttributes = property.CustomAttributes;
backingField.Name = property.Name;
type.Members.Remove(property);
}
private static CodeMemberField GetBackingField(CodeMemberProperty property, CodeTypeDeclaration type)
{
var getterExpression = ((CodeMethodReturnStatement)property.GetStatements[0]).Expression;
var backingFieldName = ((CodeFieldReferenceExpression)getterExpression).FieldName;
return type.Members.OfType<CodeMemberField>().Single(x => x.Name == backingFieldName);
}