我正在使用 System.Xaml.XamlServices.Save 方法序列化具有公共(public) getter/私有(private) setter 属性的对象,并且根据设计,这些属性将被忽略。我尝试实现 advice如何覆盖默认 XAML 绑定(bind)并序列化私有(private)属性,但由于某种原因它不起作用 - 这些属性仍然被忽略。谁能指出哪里出了问题:
public class CustomXamlSchemaContext : XamlSchemaContext
{
protected override XamlType GetXamlType(string xamlNamespace, string name, params XamlType[] typeArguments)
{
var type = base.GetXamlType(xamlNamespace, name, typeArguments);
return new CustomXamlType(type.UnderlyingType, type.SchemaContext, type.Invoker);
}
}
public class CustomXamlType : XamlType
{
public CustomXamlType(Type underlyingType, XamlSchemaContext schemaContext, XamlTypeInvoker invoker) : base(underlyingType, schemaContext, invoker)
{
}
protected override bool LookupIsConstructible()
{
return true;
}
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
{
var member = base.LookupMember(name, skipReadOnlyCheck);
return new CustomXamlMember(member.Name, member.DeclaringType, member.IsAttachable);
}
}
public class CustomXamlMember : XamlMember
{
public CustomXamlMember(string name, XamlType declaringType, bool isAttachable) : base(name, declaringType, isAttachable)
{
}
protected override bool LookupIsReadOnly()
{
return false;
}
}
public static string Save(object instance)
{
var stringWriter1 = new StringWriter(CultureInfo.CurrentCulture);
var stringWriter2 = stringWriter1;
var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };
using (var writer = XmlWriter.Create(stringWriter2, settings))
{
Save(writer, instance);
}
return stringWriter1.ToString();
}
public static void Save(XmlWriter writer, object instance)
{
if (writer == null)
throw new ArgumentNullException("writer");
using (var xamlXmlWriter = new XamlXmlWriter(writer, new CustomXamlSchemaContext()))
{
XamlServices.Save(xamlXmlWriter, instance);
}
}
具有上述基础结构代码和一个类
public class Class1
{
public string Property1 { get; private set; }
public string Property2 { get; set; }
public DateTime AddedProperty { get; set; }
}
并序列化此类的实例
var obj = new Class1 { Property1 = "value1", Property2 = "value2" };
var objString = Save(obj);
我得到了结果
<Class1 AddedProperty="0001-01-01" Property2="value2" xmlns="clr-namespace:TestNamespace;assembly=Tests" />
其中没有 Property1 条目。
更有趣的是,在序列化期间没有调用任何重载。
最佳答案
事实证明,对我的初始代码进行一些调整就解决了问题。最终解决方案如下:
private class CustomXamlSchemaContext : XamlSchemaContext
{
public override XamlType GetXamlType(Type type)
{
var xamlType = base.GetXamlType(type);
return new CustomXamlType(xamlType.UnderlyingType, xamlType.SchemaContext, xamlType.Invoker);
}
}
private class CustomXamlType : XamlType
{
public CustomXamlType(Type underlyingType, XamlSchemaContext schemaContext, XamlTypeInvoker invoker)
: base(underlyingType, schemaContext, invoker)
{
}
protected override bool LookupIsConstructible()
{
return true;
}
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
{
var member = base.LookupMember(name, skipReadOnlyCheck);
return member == null ? null : new CustomXamlMember((PropertyInfo)member.UnderlyingMember, SchemaContext, member.Invoker);
}
protected override IEnumerable<XamlMember> LookupAllMembers()
{
foreach (var member in base.LookupAllMembers())
{
var value = new CustomXamlMember((PropertyInfo)member.UnderlyingMember, SchemaContext, member.Invoker);
yield return value;
}
}
protected override bool LookupIsPublic()
{
return true;
}
}
private class CustomXamlMember : XamlMember
{
public CustomXamlMember(PropertyInfo propertyInfo, XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
: base(propertyInfo, schemaContext, invoker)
{
}
protected override bool LookupIsReadOnly()
{
return false;
}
protected override bool LookupIsWritePublic()
{
return true;
}
}
此自定义允许使用公共(public) getter 和公共(public)/内部/ protected /私有(private) setter 序列化/反序列化属性。它忽略所有其他属性。它还序列化内部类的实例。
关于c# - 公共(public)获取/私有(private)设置属性的 XAML 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8309611/