在公约中使用Castle DynamicProxy和StructureMap 3的装饰 - DecorateAllWith

时间:2014-10-16 22:30:47

标签: structuremap structuremap3

如何使用DecorateAllWith使用DynamicProxy进行装饰,所有实例都实现了一个接口?

例如:

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 ...??
        }
    }
}

我可以使用(例如):

来装饰一些具体类型的接口
var proxyGenerator = new ProxyGenerator();
registry.For<IApplicationService>().Use<BaseAppService>().DecorateWith(service => proxyGenerator.CreateInterfaceProxyWithTargetInterface(....))

但是无法使用DecorateAll来做到这一点。

致电registry.For<>().Use<>().DecorateWith()我必须这样做:

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);
}

只为疯狂的头脑......

我开始厌倦了StructureMap,很多变化而且没有文档,我已经阅读了源代码但是...为我的目标做了太多的努力......

如果有人能给我一些启示,我将不胜感激。

提前致谢。

另外...我在这里发布了我的帮助器的真实代码,用于生成表达式树的寄存器插件系列:

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);
    }

}

1 个答案:

答案 0 :(得分:3)

差不多两年后,我需要将这个问题归还给一个新项目。这次我使用了StructureMap 4解决了这个问题。

您可以使用自定义拦截器策略来修饰其类型函数的实例。您必须实现一个拦截器,一个拦截器策略并在注册表上配置它。

拦截器

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();

你可以在这个要点https://gist.github.com/tolemac/3e31b44b7fc7d0b49c6547018f332d68上得到一个有效的例子,在要点中你可以找到三种类型的装饰,第三种就像这个答案。

使用它可以轻松配置服务的装饰器。