c# - 公共(public)获取/私有(private)设置属性的 XAML 序列化

标签 c# xaml c#-4.0

我正在使用 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/

相关文章:

c# - 从 ViewModel 将数据绑定(bind)到 View 中的 XAML 控件的正确设计

.net - 在控件上设置边距、宽度绑定(bind)到实际宽度会导致 VS2012 崩溃

json - 在 C# 4.0 中解析 JSON

c# - 按值对 ConcurrentDictionary 进行排序

c# - 有没有办法将 Console.Write 的结果连续镜像到集合(数组、列表等)?

c# - DragDrop 事件之后是否有事件发生?

c# - c#中调用泛型方法时的速记

c# - 多播委托(delegate) C#

c# - 如何在 C# 中的枢轴后创建两个暗数组

c# - 通过函数绑定(bind)文本