Castle DynamicProxy CreateClassProxyWithTarget not using underlying object for non-intercepted properties

StackOverflow https://stackoverflow.com/questions/22417654

  •  15-06-2023
  •  | 
  •  

Question

I have some simple DTO classes like:

[XmlType]
class Person : AbstractResource
{
  [XmlElement("name")]
  public virtual string FirstName { get; set; }

  public virtual string Nickname { get { return "Mister cool"; } }
}

class SpecialPerson : Person
{
  public override string NickName { get { return FirstName; } }
}

In my code I deserialise a list of Person/SpecialPerson objects from an XML file and then try to wrap them all in proxy instances with CreateClassProxyWithTarget. For some reason FirstName is always null and NickName is null for any SpecialPerson proxy but returns "Mister cool" for any Person proxy.

I went into the debugger and looked at the underlying wrapped object and it has all the correct values. I have also taken care not to intercept on FirstName or Nickname. I would expect the proxy to simply call the wrapped object and in some cases it does [1] but for most it does not. What am I doing wrong?

[1] In my interceptor code I set, via reflection, some of the properties of the wrapped object and those show up correctly. But I don't see why those properties would read from the underlying object but others will not. It's almost as if any intercepted properties will always call the wrapped object when Invoke is called but for any methods you have returned false for the ShouldInterceptMethod it does not. But that would make no sense to me, if I say not to intercept a method on a wrapped object what other possible action should be taken but simply using the properties from the wrapped object?

Was it helpful?

Solution

Oh dear, I feel bad about answering my own question but I worked out what was going wrong and I hope this will help anyone else who gets in this situation. I was unable to find anything on google about this.

So the issue is, even when you create a proxy that wraps an existing object (i.e. with CreateClassProxyWithTarget) it still creates a whole new object. It just happens that that object has a way of getting the wrapped object. For any methods, properties, etc. that you do not intercept they will be called on the proxy object. And in the case of properties, these will not use the value in the wrapped object, even if the properties are virtual because the proxy object has its own copy of all those properties.

To solve this, you have to get rid of your selection hook and just intercept everything. If it is a property you don't actually want to intercept you can simply call invocation.Proceed. This will cause it to forward the request to the wrapped object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top