5

如何使用DecorateAllWithDynamicProxy 来装饰所有实例都实现了一个接口?

例如:

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

}
4

1 回答 1

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,在要点中您可以找到三种类型的装饰,第三种就像这个答案。

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

于 2016-06-07T06:42:02.803 回答