使用CodeDOM生成字段而不是属性

时间:2016-08-11 14:17:00

标签: c# xsd codedom

我使用CodeDOM从XSD架构文件创建了一些代码:

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);
}

现在在我的后期处理中,我意识到这段代码将生成如下属性:

bool prop1Field;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public bool Prop1
{
    get
    {
        return prop1Field;
    }
    set
    {
        prop1Field = value;
    }
}

但我希望生成器只是简单地生成字段。有没有办法实现这个目标?我知道xsd.exe在使用/f - 参数时也会生成字段。

编辑:之后我想用自动属性替换它们。要使用当前方法,我必须从属性中删除后备字段及其在生成的代码中出现的所有内容。但是,如果CodeDOM首先生成public字段,我所要做的就是删除此字段,使用CodeSnippedTypeMember创建一个具有相同名称的新属性,如this answer所示。因此,我不需要搜索代码以查找私有后备字段的出现,并通过调用属性来替换它们。

1 个答案:

答案 0 :(得分:0)

不,没有选项可以设置为允许这样做,因为如果您的属性是字段或属性(假设我们不使用反射)并且公共字段被认为是不好的做法,那么消费代码应该无关紧要。

无论如何,我找到了一种方法来实现这一点,方法是将属性的所有注释和属性复制到私有后备字段并将该字段设为公共。但请记住,这样做主要是一个糟糕的设计理念。

    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);
    }