Skip to content

Interface interception fails when used with open generic assembly scanning #27

Open
@tillig

Description

@tillig

This comes from a StackOverflow question

Using assembly scanning in conjunction with interface interception yields an exception:

The component ... cannot use interface interception as it provides services that are not publicly visible interfaces. Check your registration of the component to ensure you're not enabling interception and registering it as an internal/private interface type.

Code to reproduce the issue as a console app:

namespace InterceptorRepro
{
    public interface ICommand<TResult>
    {
    }

    public class StringCommand : ICommand<String>
    {
    }

    public interface ICommandHandler<TCommand, TResult>
        where TCommand : ICommand<TResult>
    {
        TResult Execute(ICommand<TResult> command);
    }

    public class StringCommandHandler : ICommandHandler<StringCommand, String>
    {
        public string Execute(ICommand<string> command)
        {
            return "generic-method";
        }
    }

    public class LoggingInterceptor : IInterceptor
    {
        TextWriter _output;

        public LoggingInterceptor(TextWriter output)
        {
            _output = output;
        }

        public void Intercept(IInvocation invocation)
        {
            _output.Write("Calling method {0} from LoggingInterceptor", invocation.Method.Name);
            invocation.Proceed();
            _output.WriteLine("LoggingInterceptor complete.");
        }
    }

    public class Program
    {
        public static void Main()
        {
            var builder = new ContainerBuilder();
            builder.Register(c => Console.Out).As<TextWriter>();
            builder.RegisterType<LoggingInterceptor>();
            builder
                .RegisterAssemblyTypes(typeof(Program).Assembly)
                .AsClosedTypesOf(typeof(ICommandHandler<,>))
                .EnableInterfaceInterceptors()
                .InterceptedBy(typeof(LoggingInterceptor));

            var container = builder.Build();

            try
            {
                using (var scope = container.BeginLifetimeScope())
                {
                    // Exception thrown on this resolve:
                    var handler = scope.Resolve<ICommandHandler<StringCommand, string>>();
                    Console.WriteLine("Handler type is: {0}", handler.GetType());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

If you remove the EnableInterfaceInterceptors() and InterceptedBy() calls from the registration then the resolution proceeds as expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions