1

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

2
  • "but looks like DryIoc doesn't support open generic delegates" - What would be the imaginary syntax to register such delegate? Commented Nov 14, 2020 at 21:19
  • I was thinking about something like this container.RegisterDelegate(typeof(IFoo<>), x => x.Resolve(_proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface( x.ResolveServiceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default))); Commented Nov 16, 2020 at 8:41

1 Answer 1

0

Yeah, it is possible. So you need to find the closed type to pass it to the proxy? Wrap the code into the method and use the Made.Of which has access to the Request.ServiceType.

Sign up to request clarification or add additional context in comments.

4 Comments

Could you be more specific, I was trying something like this: container.Register(typeof(IFoo<>), typeof(Foo<>), made: Made.Of(r => _proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface( r.ServiceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default)), setup: Setup.DecoratorOf(useDecorateeReuse: true));
I finally made it working!!! I was missing Parameters.Of bit. container.Register(typeof(IFoo<>), typeof(Foo<>)); container.Register<FooLoggingInterceptor>(Reuse.Singleton); container.Register(typeof(IFoo<>), made: Made.Of(r => _proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface( r.ServiceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default), Parameters.Of.Type<IInterceptor[]>(typeof(FooLoggingInterceptor[]))), setup: Setup.DecoratorOf(useDecorateeReuse: true));
Glad to here. You may answer your own question and I will upvote and if you Ok, I will copy (steal) your solution into DryIoc documentation.
Absolutelly, please add it to DryIoc doc. Thank you for great product and support.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.