0
votes

I am trying to create a proxy type using mixins. In the following example, TypePresenter implements ICustomTypeDescriptor. When I create an instance the "GetProperties" throws a NotImplementedException.

When I do the same thing with ProxyGenerator.CreateClassProxy, everything works fine! I want to get the type so that I can use it with my IoC.

var options = new ProxyGenerationOptions();
options.AddMixinInstance(new TypePresenter<SampleViewModel>());

var builder = new DefaultProxyBuilder();
var sampleType = builder.CreateClassProxyType(typeof(SampleViewModel), null, options);
var sample = Activator.CreateInstance(sampleType);

var typeDescriptor = (ICustomTypeDescriptor)sample;

// Error happens on this line.
var properties = typeDescriptor.GetProperties();

var property = properties["DoIt"];
Assert.IsNotNull(property);
Assert.IsTrue(property.PropertyType == typeof(ICommand));

Why does this not work?

1

1 Answers

1
votes

You are creating your sample object from the Activator; since you are not using the Castle-DynamicProxy library to create the proxy the mixin properties cannot work since the wiring behind the mixin is done via an intereceptor.

You can simply create the sample first via the ProxyGenerator then cast it to ICustomTypeDescriptor, you don't really need its type:

var options = new ProxyGenerationOptions();
options.AddMixinInstance(new TypePresenter<SampleViewModel>());

var pg = new ProxyGenerator();
var sample = pg.CreateClassProxy<SampleViewModel>(options); 
// regarding
//var sampleType = sample.GetType();

var typeDescriptor = (ICustomTypeDescriptor)sample;

// Error doesn't happen anymore on this line.
var properties = typeDescriptor.GetProperties();

Edit Reagrding building a type without knowing the constructor in advance, one can use the CreateClassProxy overload that takes an object[] of constructor parameters as an argument;

Given and interface that lets us define the parameters we will need for a type:

public interface IGiveConstructorParametersFor<T> {
    object[] Parameters {get;}
}

it is possible to register it against a concrete class (or even multiple concrete classes that would then be resolved depending on the scenario we are in). Then we can have the following method to build a type we don't know in advance with constructor parameters we don't know in advance:

public T Proxify<T>(IGiveConstructorParametersFor<T> constructorParametersForT) {
    var options = new ProxyGenerationOptions();
    options.AddMixinInstance(new TypePresenter<T>());

    var pg = new ProxyGenerator();
    var sample = pg.CreateClassProxy(typeof(T),
                                     null,
                                     options,
                                     constructorParametersForT.Parameters);

    var typeDescriptor = (ICustomTypeDescriptor)sample;
    var properties = typeDescriptor.GetProperties();
}

As long as any type can be mapped to an implementation of the constructor parameters interface at runtime, it doesn't need to know it beforehand