EF生成的POCO的MetadataType伙伴类 - XmlSerializer忽略属性

时间:2014-02-03 18:52:05

标签: c# .net xml-serialization entity-framework-5

我首先使用的是EF5数据库。为了序列化生成的POCO类,我需要使用XMLIgnore属性,如下所示

    public partial class Demographics
{
    public string KeyTract { get; set; }
    public string CollectionYear { get; set; }
    public string MSAFIPS { get; set; }
    ...
    ...
    ...
    [XmlIgnore()]
    public virtual ICollection<LoanApp> LoanApps { get; set; }
}

为了防止在每次我从数据库中重新创建模型时添加这个,我添加了一个“伙伴类”

    [MetadataType(typeof(Demographic_Metadata))]
public partial class Demographics
{
}

public class Demographic_Metadata
{
    [XmlIgnore()]
    public virtual ICollection<LoanApp> LoanApps { get; set; }
}

但是当我尝试使用XmlSerializer序列化Demographics对象时,我得到“反映类型的错误......人口统计数据”。

在研究SO时,似乎XMLSerializer忽略了伙伴类。但有没有人找到一个解决方法,以避免每次重新生成POCO类时添加XMLIgnore属性?

1 个答案:

答案 0 :(得分:1)

您可以通过使用传递XmlAttributeOverrides的XmlSerializer重载来执行此操作。我们需要做的就是通过TypeDescriptor填充它并创建一个ICustomAttributeProvider。

首先,ICustomAttributeProvider是最简单的,主要是因为我只是忽略了inhert标志并且总是返回所有属性。我们的想法是,我们将传递我们希望XmlSerializer了解的属性。

public class CustomAttributeProvider : ICustomAttributeProvider
{
    private readonly object[] _attributes;

    public CustomAttributeProvider(params Attribute[] attributes)
    {
        _attributes = attributes;
    }

    public CustomAttributeProvider(AttributeCollection attributeCollection)
        : this(attributeCollection.OfType<Attribute>().ToArray())
    {
    }

    public object[] GetCustomAttributes(bool inherit)
    {
        return _attributes;
    }

    public object[] GetCustomAttributes(Type attributeType, bool inherit)
    {
        return _attributes.Where(attributeType.IsInstanceOfType).ToArray();
    }

    public bool IsDefined(Type attributeType, bool inherit)
    {
        return _attributes.Any(attributeType.IsInstanceOfType);
    }
}

现在我要创建一个工厂方法来创建XMLAttributeOverrides。

我们需要告诉TypeDescriptor关于好友类以及将AssociatedMetadataTypeTypeDescriptionProvider添加到提供者列表的内容。

由此我们使用TypeDescriptor来读取类属性和属性。由于好友类不允许使用字段,TypeDescriptor也不会读取字段,所以我对字段使用反射。

public static class BuddyClass
{
    public static XmlAttributeOverrides CreateXmlAttributeOverrides(Type type)
    {
        // Tell TypeDescriptor about the buddy class
        TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(type), type);
        var xmlAttributeOverrides = new XmlAttributeOverrides();
        xmlAttributeOverrides.Add(type, new XmlAttributes(new CustomAttributeProvider(TypeDescriptor.GetAttributes(type))));

        foreach (PropertyDescriptor props in TypeDescriptor.GetProperties(type))
        {
            if (props.Attributes.Count > 0)
            {
             xmlAttributeOverrides.Add(type, props.Name, new XmlAttributes(new CustomAttributeProvider(props.Attributes)));
            }
        }

        foreach (var field in type.GetFields())
        {
            var attributes = field.GetCustomAttributes(true).OfType<Attribute>().ToArray();
            if (attributes.Any())
            {
                xmlAttributeOverrides.Add(type, field.Name, new XmlAttributes(new CustomAttributeProvider(attributes)));
            }
        }

        return xmlAttributeOverrides;
    }
}

你会称之为

var serializer = new XmlSerializer(typeof(Test), BuddyClass.CreateXmlAttributeOverrides(typeof(Test)));

然后就像你通常那样的用户序列化器。这不会处理参数或返回值的属性。