Question

Suppose we have an interface ICat that is derived from ICatBase and ICatExtension as shown below. For both distinct interfaces, an implementation is available, CatBase and CatExtension. How can Castle's DynamicProxy be used to merge these into an instance of ICat?

Is it possible to create a proxy in which ICatExtension is implemented by CatExtension and ICatBase is 'implemented' by an interceptor? How can this be achieved?

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

public interface ICatExtension
{
   string Description { get; }
}

public interface ICat : ICatBase, ICatExtension
{
}

public class CatBase : ICatBase
{
   public string Name { get; set; }
   public int Age { get; set; }
}

public class CatExtension : ICatExtension
{
   public string Description
   {
      get { return "Furry"; }
   }
}

EDIT

I have been trying to use mixins to make this work, but the code below results in a NotImplementedException.

var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new CatBase());
options.AddMixinInstance(new CatExtension());
var cat  = generator.CreateInterfaceProxyWithoutTarget<ICat>(options);        
cat.Name = "Joey";

This is a DynamicProxy2 error: There are no interceptors specified for method 'Void set_Name(System.String)' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)

I could create a custom interceptor that intercepts calls and dispatches to the correct interface, but I feel there must be an easier/better way. Am I correct?

EDIT #2

Thank you, Krzysztof! Using the lines below was the solution.

var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new CatBase());
options.AddMixinInstance(new CatExtension());

var cat = (ICat)generator.CreateClassProxyWithTarget(typeof(object), new[] { typeof(ICat)}, new object(), options);

EDIT #3

As a final step, I have configured a Windsor container to create the proxy from this example. The only way I was able to do this, was by specifying a name "Cat" and resolving an instance of System.Object by specifying the name and casting to the ICat interface afterwards.

WindsorContainer container = new WindsorContainer();
container.Register(
    Castle.MicroKernel.Registration.Component.For<object>().
        Named("Cat").
        Proxy.AdditionalInterfaces(typeof (ICat)).
        Proxy.MixIns(new CatBase()).
        Proxy.MixIns(new CatExtension())
    );

var cat = (ICat)container.Resolve(typeof(object), "Cat");

Is there a more elegant way to this in which I can just ask the container for an ICat instance, without referring to a particular name?

Was it helpful?

Solution

Mixins are what you'd normally use for that.

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