C# EF生成的POCO的MetadataType buddy类-XmlSerializer将忽略属性

C# EF生成的POCO的MetadataType buddy类-XmlSerializer将忽略属性,c#,.net,xml-serialization,entity-framework-5,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; } ... ... ... [Xml

我首先使用的是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; }
}
公共部分类人口统计
{
公共字符串KeyTract{get;set;}
公共字符串CollectionYear{get;set;}
公共字符串MSAFIPS{get;set;}
...
...
...
[XmlIgnore()]
公共虚拟ICollection LoanApps{get;set;}
}
为了避免每次从数据库重新创建模型时都添加这个,我添加了一个“buddy类”

[MetadataType(typeof(人口统计元数据))]
公共部分阶级人口统计
{
}
公共类人口统计单元元数据
{
[XmlIgnore()]
公共虚拟ICollection LoanApps{get;set;}
}
但当我尝试使用XmlSerializer序列化Demographics对象时,我得到“有一个反映类型…Demographics的错误”


在研究中,XMLSerializer似乎忽略了buddy类。但是,有没有人找到了一种解决方法来避免在每次重新生成POCO类时添加XMLIgnore属性?

您可以通过在传递XmlAttributeOverrides的地方使用XmlSerializer重载来做到这一点。我们需要做的就是通过TypeDescriptor填充它,并制作一个ICCustomAttributeProvider

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

然后像您通常会做的那样使用序列化程序。这不会处理参数或返回值的属性。

+1:@CharlesNRice:非常感谢您分享这段代码。你刚刚救了我的命,使我免于为这个完全相似的问题浪费很多时间。作为旁注,在添加对具有类似名称的库的引用后,可以在命名空间[System.ComponentModel.DataAnnotations]下使用AssociatedMetadataTypeDescriptorProvider()。
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);
    }
}
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)));