I'm using System.Xaml.XamlServices.Save method to serialize an object which has properties with public getters/private setters and by design these properties are ignored. I tried to implement advice of how to override default XAML bindings and get private properties serialized, but it doesn't work for some reason - those properties are still ignored. Could anyone point out what's wrong:
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);
}
}
Having above infrastructure code and a class
public class Class1
{
public string Property1 { get; private set; }
public string Property2 { get; set; }
public DateTime AddedProperty { get; set; }
}
and serializing an instance of this class with
var obj = new Class1 { Property1 = "value1", Property2 = "value2" };
var objString = Save(obj);
I get the result
<Class1 AddedProperty="0001-01-01" Property2="value2" xmlns="clr-namespace:TestNamespace;assembly=Tests" />
where there is no entry for Property1.
What's even more interesting, that none of the overloads are called during serialization.