如何在运行时设置属性序列化属性?

时间:2019-01-31 12:10:12

标签: c# serialization dynamic runtime xml-serialization

我有一个简单的类作为测试:

public class TEST
{
     public string PropertyOne { get; set; }
     public string PropertyTwo { get; set; }
}

我想将该类序列化为XML,但是当我这样做时;我想在运行时指定如何序列化它。仅PropertyOne,仅PropertyTwo或两者兼有。

我发现您可以通过在不需要序列化的属性上使用[XmlIgnore]属性来正常实现此目的。然后,我尝试了此处说明的方法:

How to add property-level Attribute to the TypeDescriptor at runtime?

但是由于某种原因,它根本不起作用。这是我的代码:

TEST testInstance = new TEST();
testInstance.PropertyOne = "One";
testInstance.PropertyTwo = "Two";

SetAttributesToObjectOnProperty(testInstance, "PropertyOne");

using (StringWriter mainStringWriter = new StringWriter())
{
    XmlSerializer mainXMLSerializer = new XmlSerializer(testInstance.GetType());
    mainXMLSerializer.Serialize(mainStringWriter, testInstance);
    string theXMLToWrite = mainStringWriter.ToString();
}

public static void SetAttributesToObjectOnProperty(object classInstanceToCheck, string propertyName)
{
        if (propertyName != null && classInstanceToCheck != null)
        {
            // Prepare the Property Overriding Type Descriptor
            PropertyOverridingTypeDescriptor mainPropertyOverridingTypeDescriptor = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(classInstanceToCheck).GetTypeDescriptor(classInstanceToCheck));

            // Iterate through properies in the supplied Object / Type
            foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(classInstanceToCheck))
            {
                if (propertyDescriptor.Name == propertyName)
                {
                    System.Xml.Serialization.XmlIgnoreAttribute theXMLIgnoreAttributToAdd = new System.Xml.Serialization.XmlIgnoreAttribute();

                    PropertyDescriptor newPropertyDescriptor = TypeDescriptor.CreateProperty(classInstanceToCheck.GetType(), propertyDescriptor, theXMLIgnoreAttributToAdd);

                    // Set the new PropertyOverridingTypeDescriptor to override that property
                    mainPropertyOverridingTypeDescriptor.OverrideProperty(newPropertyDescriptor);

                    break;
                }
            }

            // Add the new descriptor provider that will return our descriptor instead of default
            TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(mainPropertyOverridingTypeDescriptor), classInstanceToCheck);
        }
}



    public static void SetAttributesToObjectOnProperty(object classInstanceToCheck, string propertyName)
    {
        try
        {
            if (propertyName != null)
            {
                // Prepare the Property Overriding Type Descriptor
                PropertyOverridingTypeDescriptor mainPropertyOverridingTypeDescriptor = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(classInstanceToCheck).GetTypeDescriptor(classInstanceToCheck));

                // Iterate through properies in the supplied Object / Type
                foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(classInstanceToCheck))
                {
                    if (propertyDescriptor.Name == propertyName)
                    {
                        System.Xml.Serialization.XmlIgnoreAttribute theXMLIgnoreAttributToAdd = new System.Xml.Serialization.XmlIgnoreAttribute();

                        PropertyDescriptor newPropertyDescriptor = TypeDescriptor.CreateProperty(classInstanceToCheck.GetType(), propertyDescriptor, theXMLIgnoreAttributToAdd);

                        // Set the new PropertyOverridingTypeDescriptor to override that property
                        mainPropertyOverridingTypeDescriptor.OverrideProperty(newPropertyDescriptor);

                        break;
                    }
                }

                // Add the new descriptor provider that will return our descriptor instead of default
                TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(mainPropertyOverridingTypeDescriptor), classInstanceToCheck);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error at 'SetAttributesToObjectOnProperty'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

    public class PropertyOverridingTypeDescriptor : CustomTypeDescriptor
    {
        // Fields
        private readonly Dictionary<string, PropertyDescriptor> OverridePropertyDescriptors = new Dictionary<string, PropertyDescriptor>();

        // Constructor
        public PropertyOverridingTypeDescriptor(ICustomTypeDescriptor parent) : base(parent) { }

        // Methods
        public void OverrideProperty(PropertyDescriptor thePropertyDescriptor)
        {
            try
            {
                OverridePropertyDescriptors[thePropertyDescriptor.Name] = thePropertyDescriptor;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'OverrideProperty'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        public override object GetPropertyOwner(PropertyDescriptor thePropertyDescriptor)
        {
            try
            {
                object toReturn = base.GetPropertyOwner(thePropertyDescriptor);

                if (toReturn == null)
                {
                    return this;
                }

                return toReturn;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'GetPropertyOwner'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
        }
        public PropertyDescriptorCollection GetPropertiesMain(PropertyDescriptorCollection thePropertyDescriptorCollection)
        {
            try
            {
                List<PropertyDescriptor> mainPropertyDescriptorList = new List<PropertyDescriptor>(thePropertyDescriptorCollection.Count + 1);

                foreach (PropertyDescriptor propertyDescriptor in thePropertyDescriptorCollection)
                {
                    if (OverridePropertyDescriptors.ContainsKey(propertyDescriptor.Name))
                    {
                        mainPropertyDescriptorList.Add(OverridePropertyDescriptors[propertyDescriptor.Name]);
                    }
                    else
                    {
                        mainPropertyDescriptorList.Add(propertyDescriptor);
                    }
                }

                PropertyDescriptorCollection toReturn = new PropertyDescriptorCollection(mainPropertyDescriptorList.ToArray());

                return toReturn;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'GetPropertiesMain'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
        }
        public override PropertyDescriptorCollection GetProperties()
        {
            try
            {
                return GetPropertiesMain(base.GetProperties());
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'GetProperties'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
        }
        public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            try
            {
                return GetPropertiesMain(base.GetProperties(attributes));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'GetProperties'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
        }
    }

    public class TypeDescriptorOverridingProvider : TypeDescriptionProvider
    {
        // Fields
        private readonly ICustomTypeDescriptor MainCustomTypeDescriptor;

        // Constructor
        public TypeDescriptorOverridingProvider(ICustomTypeDescriptor theCustomTypeDescriptor)
        {
            try
            {
                this.MainCustomTypeDescriptor = theCustomTypeDescriptor;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at Constructor 'TypeDescriptorOverridingProvider'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // Methods
        public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
        {
            try
            {
                return MainCustomTypeDescriptor;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error at 'GetTypeDescriptor'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
        }
    }

没有例外,它仍然将两个序列化。

我不知道我是否使用了不正确的方法,或者是否在这里缺少其他东西。

我想在其他较大的分类上使用此方法,并尝试使用其他XML属性。

0 个答案:

没有答案