繁体   English   中英

如何从XSD生成类,但保持属性不变?

[英]How can I generate a class from an XSD but, keep attributes the same?

我正在从数据库接收XML,并尝试将其处理到我的系统中。 我已经从另一个团队收到的XSD生成了一个类。 我遇到的问题是,现在XSD中的属性名称与我的应用程序(典型)中的属性名称不匹配。 为了使我能够构建一个可以使用的对象,我必须创建一个对象并将其与XML结合在一起。 像这样:

DynamicEntity auth = new DynamicEntity(EntityAuthorization);
auth.Properties["DealerId] = authprm.new_dealerid[0].Value;
auth.Properties["CarId"] = authprm.new_carid[0].Value;
etc...

我可能要设置40到100个属性。 我曾考虑过将XmlElement应用于类属性,但是每次(从XML)重新生成类时,我都会丢失之前应用的XmlElement。 有什么建议吗?

感谢大家!

您可以通过将MetadataTypeAttribute放在类上来使用元数据“伙伴类”。 我将使生成的类(如果尚未生成)成为局部的,然后创建另一个局部类,并将MetadataType Attribute添加到该类。 然后,如果您从XSD重新生成该类,而该类不是局部的,则编译器会抱怨,您会记住将其局部化。

我不太喜欢“伙伴类”,因为属性是重复的,不是真正的DRY,但这可能是您正在寻找的解决方案。 对于元数据类的简单概述,通常与验证属性有关,但是它适用于任何属性,您可以在此处的 MS上找到

您可以查看答案https://stackoverflow.com/a/26724847/1798889 ,了解如何使XmlSerializer了解伙伴类。

更新

现在,我考虑了一下,如果您不想使用Buddy类,则可以构建一个流畅的api来配置XML Serializer。

我们将保留带有伙伴类问题XMLSerializer中的CustomAttributeProvider类,但改用XmlSerializerConfigurator类。

public class XmlSerializerConfigurator<T>
{
    private readonly XmlAttributeOverrides _xmlAttributeOverrides;

    public XmlSerializerConfigurator(XmlAttributeOverrides xmlAttributeOverrides)
    {
        _xmlAttributeOverrides = xmlAttributeOverrides;
    }

    public XmlSerializerConfigurator() : this(new XmlAttributeOverrides())
    {
    }

    /// <summary>
    /// Adds attributes to properties or fields and strongly typed
    /// </summary>
    /// <typeparam name="TData"></typeparam>
    /// <param name="property"></param>
    /// <param name="xmlAttributes"></param>
    /// <returns></returns>
    public XmlSerializerConfigurator<T> AddPropertyOrFieldAttributes<TData>(Expression<Func<T, TData>> property,
                                                    params Attribute[] xmlAttributes)
    {
        var memberName = property.GetName();
        _xmlAttributeOverrides.Add(typeof (T), memberName,
                                   new XmlAttributes(new CustomAttributeProvider(xmlAttributes)));
        return this;
    }

    /// <summary>
    /// Adds class level attributes
    /// </summary>
    /// <param name="xmlAttributes"></param>
    /// <returns></returns>
    public XmlSerializerConfigurator<T> AddClassLevelAttributes(params Attribute[] xmlAttributes)
    {
        _xmlAttributeOverrides.Add(typeof(T), new XmlAttributes(new CustomAttributeProvider(xmlAttributes)));
        return this;
    }

    /// <summary>
    /// Creates an XmlSerializerConfigurator that is tied to the main one
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <returns></returns>
    public XmlSerializerConfigurator<K> ChildClassConfigurator<K>()
    {
        // passes in own XmlAttributeOverrides and since object reference it will fill the same object 
        return new XmlSerializerConfigurator<K>(_xmlAttributeOverrides);
    }

    /// <summary>
    /// Returns back an XmlSerializer with this configuration
    /// </summary>
    /// <returns></returns>
    public XmlSerializer GetSerializer()
    {
        return new XmlSerializer(typeof(T), _xmlAttributeOverrides);
    }
}

此类可让您配置序列化程序的类/属性上的属性,而不依赖于伙伴类。 当该类具有另一个类作为属性时,我们需要ChildClassAttributes来配置该类。

另外,我使用扩展方法,该方法从名为GetName的表达式返回属性或字段。

public static string GetName<TEntity, TData>(this Expression<Func<TEntity, TData>> field)
{
    var name = "";

    if (field.Body is MemberExpression)
    {
        var body = field.Body as MemberExpression;
        var ebody = body.Expression as MemberExpression;

        if (ebody != null)
        {
            name = ebody.Member.Name + ".";
        }
        name = name + body.Member.Name;
    }
    else if (field.Body is UnaryExpression)
    {
        var ubody = field.Body as UnaryExpression;
        var body = ubody.Operand as MemberExpression;
        var ebody = body.Expression as MemberExpression;

        if (ebody != null)
        {
            name = ebody.Member.Name + ".";
        }
        name = name + body.Member.Name;
    }
    else if (field.Body is ConstantExpression)
    {
        var cbody = field.Body as ConstantExpression;
        name = cbody.Value.ToString();
    }
    else
    {
        throw new InvalidOperationException(String.Format("{0} not supported.", field));
    }

    return name;
}

现在您可以通过这种方式使用/配置它

var xmlConfiguration = new XmlSerializerConfigurator<Group>();
xmlConfiguration.AddPropertyOrFieldAttributes(x => x.Employees, new XmlArrayItemAttribute(typeof (Employee)),
                                              new XmlArrayItemAttribute(typeof (Manager)));
xmlConfiguration.AddClassLevelAttributes(new XmlRootAttribute("GroupName"));
var childConfiguration = xmlConfiguration.ChildClassConfigurator<Employee>();
childConfiguration.AddPropertyOrFieldAttributes(x => x.FullName, new XmlElementAttribute("Name"));
var xmlSerializer = xmlConfiguration.GetSerializer();

现在,所有属性和字段都是强类型的,并且在伙伴类中不再重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM