Registration by convention and interception causes ResolutionFailedException

非 Y 不嫁゛ 提交于 2019-12-12 01:49:10

问题


Simple scenario

public interface IFoo
{
   int GetData();
}

public class Foo : IFoo
{
    [CacheResult]
    public int GetData() { .... }
}

public class MyController
{
    [Dependency]
    IFoo Foo {get; set;}
}

If I register the interface manually, resolving MyController works fine:

container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager(),
    new InterceptionBehavior<PolicyInjectionBehavior>(),
    new Interceptor<InterfaceInterceptor>());

var controller = container.Resolve<MyController>();

If I try to use auto-registration:

        container.RegisterTypes(
            AllClasses.FromLoadedAssemblies(),
            WithMappings.FromMatchingInterface,
            WithName.Default,
            WithLifetime.ContainerControlled,
            getInjectionMembers: t => new InjectionMember[]
            {
                new Interceptor<InterfaceInterceptor>(),
                new InterceptionBehavior<PolicyInjectionBehavior>(),
            });

var controller = container.Resolve<MyController>();

The resolve fails with a ResolutionFailedException because the Type passed must be an interface. Of course, if I make it an interface, it will work, but only if it is named Controller. If I call it, MyController or SqlController or whatever, then the mapping fails because it cannot resolve the interface.

I was hoping to just do an assembly scan, similar to what the Spring framework does, but I have not been able to figure it out.

What am I missing? Or is this not possible in Unity?


回答1:


The problem is that AllClasses.FromLoadedAssemblies is matching and registering your controller as well. Then when Unity tries to resolve the controller (not IFoo), it finds that the controller is not registered with an interface.

Here's a helper that will reduce your registrations to only those classes that have a matching interface.

public static class TypeFilters
{
    public static IEnumerable<Type> WithMatchingInterface(this IEnumerable<Type> types)
    {
        return types.Where(type => 
            type.GetTypeInfo().GetInterface("I" + type.Name) != null);
    }
}

and then you can use this to modify your registration like so...

AllClasses.FromLoadedAssemblies().WithMatchingInterface()


来源:https://stackoverflow.com/questions/29480123/registration-by-convention-and-interception-causes-resolutionfailedexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!