按约定和拦截注册会导致ResolutionFailedException

时间:2015-04-06 21:38:30

标签: unity-container unity-interception

简单场景

public interface IFoo
{
   int GetData();
}

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

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

如果我手动注册界面,解析MyController工作正常:

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

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

如果我尝试使用自动注册:

        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>();

解决方法因ResolutionFailedException而失败,因为传递的Type必须是接口。当然,如果我使它成为一个接口,它将工作,但只有它被命名为控制器。如果我调用它,MyController或SqlController或其他什么,那么映射会失败,因为它无法解析接口。

我希望只是进行一次程序集扫描,类似于Spring框架的功能,但我无法弄明白。

我错过了什么?或者这在Unity中是不可能的?

1 个答案:

答案 0 :(得分:2)

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()