使用DefaultControllerFactory中的Unity 2解析命名注册

时间:2012-06-06 16:47:34

标签: c# asp.net-mvc-3 unity-container controller-factory

我在使用ASP.NET MVC 3在DefaultControllerFactory中使用DI设置解析Unity 2中已注册类型的命名注册时遇到问题。

在一个程序集中,我已经为Unity容器定义了注册类型和命名注册

public class VisUnityContainer : UnityContainer
{
    public IUnityContainer RegisterVisComponents()
    {
         // register types
         this               
             .RegisterType<ICompanyService, CompanyService>()
             .RegisterType<ICompanyService, TestCompanyService>( "2" );
    }
}

在我的MVC项目中,我继承了DefaultControllerFactory,我正在解析类型并传递VisUnityContainer

public class UnityControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer unityContainer;

    public UnityControllerFactory( IUnityContainer unityContainer )
    {
        // set contracts
        if( unityContainer == null )
            throw new ArgumentNullException( null, "Unity container is not initialized." );

        // set associations
        this.unityContainer = unityContainer;
    }

    protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType )
    {
        // set contracts
        if( controllerType == null )
            throw new HttpException( 404, String.Format(  "The controller for path '{0}' could not be found or it does not implement IController.",
                     requestContext.HttpContext.Request.Path ) );
        if( !typeof( IController ).IsAssignableFrom( controllerType ) )
            throw new ArgumentException( String.Format( "Type requested is not a controller: {0}", controllerType.Name ) );

        // action result
        IController controller;

        // company law
        string companyLaw = String.Empty;

        // set user properties
        if( Thread.CurrentPrincipal != null &&
            Thread.CurrentPrincipal.Identity.Name != null &&
            !String.IsNullOrWhiteSpace( Thread.CurrentPrincipal.Identity.Name ) )
        {
            // set culture for law of companies region
            CultureInfo cultureInfo = new CultureInfo( Profile.GetCurrent().CompanyState );

            // set language
            CultureInfo uiCultureInfo = new CultureInfo( Profile.GetCurrent().UserLanguage );

            // set dates etc.
            Thread.CurrentThread.CurrentCulture = cultureInfo;

            // get proper resource file
            Thread.CurrentThread.CurrentUICulture = uiCultureInfo;

            // set company law
            companyLaw = Profile.GetCurrent().CompanyLaw;
        }

        try
        {
            // resolve container
            controller = this.unityContainer.Resolve( controllerType, companyLaw ) as IController;
        }
        catch( Exception )
        {
            // throw exception
            throw new InvalidOperationException( String.Format( "Error resolving controller {0}", controllerType.Name ) );
        }

        // action end
        return controller;

    }
}

问题在于行

controller = this.unityContainer.Resolve( controllerType, companyLaw ) as IController;

虽然companyLaw等于2,但它不解析命名注册TestCompanyService,但始终解析CompanyService。如果我还使用某些命名注册设置CompanyService,则会抛出一个错误,说它无法解析类型。

另外,如果我尝试手动解析类似

的类型
var test = this.unityContainer.Resolve<ICompanyService>( companyLaw );

返回正确的类型。

有人知道出了什么问题吗?

1 个答案:

答案 0 :(得分:1)

Container.Resolve(type,string)

Container.Resolve<T>(string)

没有不同的方法。

Resolve(string)实际上是一个扩展方法,在内部调用Container.Resolve(type,string)。

查看代码,“controllerType”是一个类还是接口?如果“controllerType”是一个类(CompanyService)而不是一个接口(ICompanyService),它将始终解析为CompanyService。它还可以解释为什么当你尝试

时它会出错
Resolve(controllerType,"2")

因为你在这里说的是:

container.Resolve(typeof(CompanyService),"2");

不存在。

这也可以解释为什么它在你打电话时有效:

container.Resolve<ICompanyService>("2");

因为你在这里设置了正确的界面

所以,简短回答:

我认为你传递的是具体的类类型而不是Unity的接口。应该相当容易检查。