DryIoc 用城堡核心开启通用拦截

DryIoc open generic interception with castle core

我想注册开放式通用拦截,所以我修改了来自 https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/Interception.md

的示例
[TestFixture]
public class UnitTest3
{
    public interface IFoo<T>
    {
        void Greet();
    }

    public class Foo<T> : IFoo<T>
    {
        public void Greet() { }
    }

    [Test]
    public void Example()
    {
        var container = new Container();
        container.Register(typeof(IFoo<>), typeof(Foo<>));
        container.Register<FooLoggingInterceptor>(Reuse.Singleton);
        container.Intercept<FooLoggingInterceptor>(typeof(IFoo<>));

        var foo = container.Resolve<IFoo<int>>();
        foo.Greet();

        // examine that logging indeed was hooked up
        var logger = container.Resolve<FooLoggingInterceptor>();
        Assert.AreEqual("Invoking method: Greet", logger.LogLines[0]);
    }
}

public class FooLoggingInterceptor : IInterceptor
{
    public List<string> LogLines = new List<string>();
    private void Log(string line) => LogLines.Add(line);

    public void Intercept(IInvocation invocation)
    {
        Log($"Invoking method: {invocation.GetConcreteMethod().Name}");
        invocation.Proceed();
    }
}

public static class DryIocInterception
{
    private static readonly DefaultProxyBuilder _proxyBuilder = new DefaultProxyBuilder();

    public static void Intercept<TInterceptor>(this IRegistrator registrator, Type serviceType, object serviceKey = null)
        where TInterceptor : class, IInterceptor
    {
        Type proxyType;
        if (serviceType.IsInterface())
            proxyType = _proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface(
                serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default); //Exception!!!
        else if (serviceType.IsClass())
            proxyType = _proxyBuilder.CreateClassProxyTypeWithTarget(
                serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default);
        else
            throw new ArgumentException(
                $"Intercepted service type {serviceType} is not a supported, cause it is nor a class nor an interface");

        registrator.Register(serviceType, proxyType,
            made: Made.Of(pt => pt.PublicConstructors().FindFirst(ctor => ctor.GetParameters().Length != 0),
                Parameters.Of.Type<IInterceptor[]>(typeof(TInterceptor[]))),
            setup: Setup.DecoratorOf(useDecorateeReuse: true, decorateeServiceKey: serviceKey));
    }
}

但这会抛出异常:

Can not create proxy for type TestDryIoc.UnitTest3+IFoo`1 because type TestDryIoc.UnitTest3+IFoo`1 is an open generic type.

显然 Castle.Core 不支持开放泛型。我的另一个想法是提供委托,这将在解析时创建代理 class,当具体的通用参数已知时,但看起来 DryIoc 不支持开放的通用委托...

是的,这是可能的。所以你需要找到封闭类型来传递给代理?将代码包装到方法中并使用可以访问 Request.ServiceType.

的 Made.Of