2014-11-03 41 views
1

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

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。有什么建议?

谢谢大家!

回答

1

通过将MetadataTypeAttribute放在班上,您可以使用元数据“好友班级”。如果它不是已经生成的类,我会让它生成partial,然后创建另一个partial类并将MetadataType Attribute添加到该类。然后,如果您从XSD重新生成类,但它不是部分,编译器会发出抱怨,并且您会记得使其部分。

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

你可以看到回答https://stackoverflow.com/a/26724847/1798889如何使XmlSerializer的了解一个哥们类。

更新

现在我想想这个,如果你不想使用好友类,你可以建立一个流畅的API来配置XML序列化。

我们将保留来自XMLSerializer with buddy class question的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); 
    } 
} 

这个类将允许你配置哪些属性在Serializer的什么类/属性上,而不是依赖于好友类。当类有另一个类时,我们需要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(); 

现在所有的属性和字段是强类型和一哥们类不重复。

+0

谢谢男人,我欣赏它! – user1158555 2014-11-04 12:31:39