0

I was struggling with non virtual members in my POCO classes using Castle's DynamicProxy generator and hit upon a way to make this happen using the ProxyGenerationOptions.AddMixinInstance() using the below code.

The question I have is why, if the mixin can send non-virtual members to the interceptor, can't the standard proxy when based on my actual type???

Below is the code.

void Main()
{
    var generator = new ProxyGenerator();

    Console.WriteLine(Environment.NewLine + "============ Proxy - With Target ===============");
    var person = new Person { Name = "Freddy FudPucker", Age = 62 };
    var personProxy = CreateProxyWithTarget(generator, person);


    Console.WriteLine(((IPerson)personProxy).Name);
    Console.WriteLine(((IPerson)personProxy).Age);
    ((IPerson)personProxy).Name = "Speedy";
    ((IPerson)personProxy).Age = 64;
    Console.WriteLine(((IPerson)personProxy).Name);
    Console.WriteLine(((IPerson)personProxy).Age);

    Console.WriteLine(((ITracking)personProxy).State);
    ((ITracking)personProxy).State = 1;
    Console.WriteLine(((ITracking)personProxy).State);
}

public object CreateProxyWithTarget(ProxyGenerator generator, Person person)
{
    var options = new ProxyGenerationOptions();
    options.AddMixinInstance(person);
    options.AddMixinInstance(new Tracking());
    return generator.CreateClassProxyWithTarget(typeof(ProxyBase), new[] { typeof(ITracking) }, new ProxyBase(), options, new PersonInterceptor());
}

Which gives the following output

Person System.String get_Name()
Freddy FudPucker
62
Person Void set_Name(System.String)
Person Void set_Age(Int32)
Person System.String get_Name()
Speedy
Person Int32 get_Age()
64
Person Int32 get_State()
0
Person Void set_State(Int32)
Person Int32 get_State()
1

Below are the supporting classes and interfaces

public class ProxyBase
{
    public ProxyBase()
    {

    }
}

public interface ITracking
{
    int State { get; set; }
}

public class Tracking : ITracking
{
    public int State { get; set; }
}


public class Person : IPerson
{
    public string Name { get; set; }

    public int Age { get; set; }
}

public interface IPerson
{
    string Name { get; set; }
    int Age { get; set; }
}

public interface IPersonAge
{
    int Age { get; set; }
}

class PersonInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"Person {invocation.Method}");
        invocation.Proceed();
    }
}
Geoff Scott
  • 897
  • 1
  • 10
  • 17

1 Answers1

0

Your class proxy with target inherits from your ProxyBase class so requires virtual members, while DynamicProxy mixins implement members of the mixin class's interfaces on that proxy class so are implicitly virtual. Effectively mixins work like interface proxies with targets.

// You can do this (from your example):
Console.WriteLine(((IPerson)personProxy).Name);

// ... but not this (because the proxy isn't a Person but is an IPerson):
Console.WriteLine(((Person)personProxy).Name);

The XML documentation for AddMixinInstance has some more detail: https://github.com/castleproject/Core/blob/e2dfb57020d9dbb4b31f3ce548b34cb35ffa3307/src/Castle.Core/DynamicProxy/ProxyGenerationOptions.cs#L208-L225

Jonathon Rossi
  • 4,149
  • 1
  • 22
  • 32