views:

26

answers:

2

Using DynamicProxy 2.2 I think I'm seeing this issue:

"Inheritable attributes on virtual properties not available on proxy"

http://support.castleproject.org/projects/DYNPROXY/issues/view/DYNPROXY-ISSUE-109

I've got a base class with a virtual property. The property is marked with [XmlIgnore]. If I serialize a derived class, the property is not serialized. But if I create a proxy for the derived class, the property IS serialized. Here's a simple console application showing the issue:

using System;
using System.Xml.Serialization;
using Castle.DynamicProxy;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            var derived = new Derived { IsDirty = true, Sample = "ABC"};
            derived.Save();
            Console.WriteLine("\n\nProxied...\n");

            var generator = new ProxyGenerator();
            var derivedProxy = generator.CreateClassProxy<Derived>();
            derivedProxy.IsDirty = true;
            derivedProxy.Sample = "ABC";
            derivedProxy.Save();

            Console.WriteLine("\n\n");
            Console.ReadKey();
        }
    }

    public abstract class Base
    {
        [XmlIgnore]
        public virtual bool IsDirty { get; set; }

        public virtual void Save()
        {
            var ser = new XmlSerializer(this.GetType());
            ser.Serialize(Console.Out, this);
        }
    }

    public class Derived : Base
    {
        public virtual string Sample { get; set; }
    }
}

Is this a bug? Or am I doing something wrong. Quick workaround is to make my IsDirty property not virtual. That may actually be acceptable in the scenario I'm working with, but I'd prefer it to be virtual.

Thanks.


Patrick Steele http://weblogs.asp.net/psteele

+1  A: 

OK, here's what I think is happening.

The problem is that your derived class does not override the IsDirtry property, whereas the proxy does.

The XmlIgnore attribute is inheritable so DP does not replicate it, however I'm guessing the serializer does not care about it, and assumes that since the attribute was not replicated it should go ahead and serialize the property.

Krzysztof Koźmic
Yup! That was exactly it. Thanks Krzysztof. If I override the property in my Derived class, I see the same behavior as DP.
Patrick Steele
A: 

Just wanted to add something to this that I found today. I could also use a proxy generation hook to skip the proxying of this particular property:

public class SkipIsDirtyProxying: IProxyGenerationHook
{
    public void MethodsInspected()
    {
    }

    public void NonVirtualMemberNotification(Type type, System.Reflection.MemberInfo memberInfo)
    {
    }

    public bool ShouldInterceptMethod(Type type, System.Reflection.MethodInfo methodInfo)
    {
        if (methodInfo.Name == "set_IsDirty" || methodInfo.Name == "get_IsDirty")
        {
            return false;
        }
        return true;
    }
}

Then just use this hook when creating the proxy generator:

var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions(new SkipIsDirtyProxying());
var derivedProxy = generator.CreateClassProxy<Derived>(options);
Patrick Steele