How to use DecorateAllWith
to decorate with a DynamicProxy all instances implements an interface?
For example:
public class ApplicationServiceInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// ...
invocation.Proceed();
// ...
}
}
public class ApplicationServiceConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.CanBeCastTo<IApplicationService>() && type.IsInterface)
{
var proxyGenerator = new ProxyGenerator();
// ??? how to use proxyGenerator??
// ???
registry.For(type).DecorateAllWith(???); // How to use DecorateAllWith DynamicProxy ...??
}
}
}
I could decorate some interfaces to concrete types using (for example):
var proxyGenerator = new ProxyGenerator();
registry.For<IApplicationService>().Use<BaseAppService>().DecorateWith(service => proxyGenerator.CreateInterfaceProxyWithTargetInterface(....))
But havent able to using DecorateAll to do this.
To call registry.For<>().Use<>().DecorateWith()
I have to do this:
if (type.CanBeCastTo<IApplicationService>() && !type.IsAbstract)
{
var interfaceToProxy = type.GetInterface("I" + type.Name);
if (interfaceToProxy == null)
return null;
var proxyGenerator = new ProxyGenerator();
// Build expression to use registration by reflection
var expression = BuildExpressionTreeToCreateProxy(proxyGenerator, type, interfaceType, new MyInterceptor());
// Register using reflection
var f = CallGenericMethod(registry, "For", interfaceToProxy);
var u = CallGenericMethod(f, "Use", type);
CallMethod(u, "DecorateWith", expression);
}
Only for crazy minds ...
I start to get very tired of StructureMap, many changes and no documentation, I have been read the source code but ... too many efforts for my objective ...
If someone can give me a bit of light I will be grateful.
Thanks in advance.
In addition ... I post here the real code of my helper to generate the expression tree an register the plugin family:
public static class RegistrationHelper
{
public static void RegisterWithInterceptors(this Registry registry, Type interfaceToProxy, Type concreteType,
IInterceptor[] interceptors, ILifecycle lifecycle = null)
{
var proxyGenerator = new ProxyGenerator();
// Generate expression tree to call DecoreWith of StructureMap SmartInstance type
// registry.For<interfaceToProxy>().Use<concreteType>()
// .DecoreWith(ex => (IApplicationService)
// proxyGenerator.CreateInterfaceProxyWithTargetInterface(interfaceToProxy, ex, interceptors)
var expressionParameter = Expression.Parameter(interfaceToProxy, "ex");
var proxyGeneratorConstant = Expression.Constant(proxyGenerator);
var interfaceConstant = Expression.Constant(interfaceToProxy);
var interceptorConstant = Expression.Constant(interceptors);
var methodCallExpression = Expression.Call(proxyGeneratorConstant,
typeof (ProxyGenerator).GetMethods().First(
met => met.Name == "CreateInterfaceProxyWithTargetInterface"
&& !met.IsGenericMethod && met.GetParameters().Count() == 3),
interfaceConstant,
expressionParameter,
interceptorConstant);
var convert = Expression.Convert(methodCallExpression, interfaceToProxy);
var func = typeof(Func<,>).MakeGenericType(interfaceToProxy, interfaceToProxy);
var expr = Expression.Lambda(func, convert, expressionParameter);
// Register using reflection
registry.CallGenericMethod("For", interfaceToProxy, new[] {(object) lifecycle /*Lifecicle*/})
.CallGenericMethod("Use", concreteType)
.CallNoGenericMethod("DecorateWith", expr);
}
}
public static class CallMethodExtensions
{
/// <summary>
/// Call a method with Generic parameter by reflection (obj.methodName[genericType](parameters)
/// </summary>
/// <returns></returns>
public static object CallGenericMethod(this object obj, string methodName, Type genericType, params object[] parameters)
{
var metod = obj.GetType().GetMethods().First(m => m.Name == methodName && m.IsGenericMethod);
var genericMethod = metod.MakeGenericMethod(genericType);
return genericMethod.Invoke(obj, parameters);
}
/// <summary>
/// Call a method without Generic parameter by reflection (obj.methodName(parameters)
/// </summary>
/// <returns></returns>
public static object CallNoGenericMethod(this object obj, string methodName, params object[] parameters)
{
var method = obj.GetType().GetMethods().First(m => m.Name == methodName && !m.IsGenericMethod);
return method.Invoke(obj, parameters);
}
}
Almost two years later I have needed return this issue for a new project. This time I have solved it this time I have used StructureMap 4.
You can use a custom interceptor policy to decorate an instance in function of his type. You have to implement one interceptor, one interceptor policy and configure it on a registry.
public class MyExInterceptor : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("-- Call to " + invocation.Method);
invocation.Proceed();
}
}
public class CustomInterception : IInterceptorPolicy
{
public string Description
{
get { return "good interception policy"; }
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (pluginType == typeof(IAppService))
{
// DecoratorInterceptor is the simple case of wrapping one type with another
// concrete type that takes the first as a dependency
yield return new FuncInterceptor<IAppService>(i =>
(IAppService)
DynamicProxyHelper.CreateInterfaceProxyWithTargetInterface(typeof(IAppService), i));
}
}
}
var container = new Container(_ =>
{
_.Policies.Interceptors(new CustomInterception());
_.For<IAppService>().Use<AppServiceImplementation>();
});
var service = container.GetInstance<IAppService>();
service.DoWork();
You can get a working example on this gist https://gist.github.com/tolemac/3e31b44b7fc7d0b49c6547018f332d68, in the gist you can find three types of decoration, the third is like this answer.
Using it you can configure the decorators of your services easily.