首页 > 解决方案 > DryIoc open generic interception with castle core

问题描述

I want to register open generic interception, so I modified explample from 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));
    }
}

But this throws exception:

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

Aparently Castle.Core doesn't support open generics. My other idea was to supply delegate, which will create the proxy class on resolve, when concrete generic param is known, but looks like DryIoc doesn't support open generic delegates...

标签: c#dependency-injectioncastle-dynamicproxydynamic-proxydryioc

解决方案


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


推荐阅读