我有一个简单的类作为测试:
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属性。