Resolving named registration using Unity 2 in Defa

2019-07-17 01:27发布

问题:

I have an issue with resolving named registrations of registered types in Unity 2 using ASP.NET MVC 3 with DI set in DefaultControllerFactory.

In one assembly I have defined Unity container with registration types and named registrations

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

and in my MVC project I have inherited DefaultControllerFactory i am resolving types and passing 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;

    }
}

The problem is with line

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

While companyLaw is equal 2 it doesn't resolve named registration TestCompanyService, but always CompanyService. If I also set CompanyService with some named registration, it throws an error saying it can't resolve a type.

Also, if I try manually to resolve a type like

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

It returns the correct type.

Does anybody have an idea what's wrong?

回答1:

Container.Resolve(type,string)

and

Container.Resolve<T>(string)

aren't different methods.

Resolve(string) is actually an extension method that, internally, calls Container.Resolve(type,string).

Looking at the code, is "controllerType" a class or interface? If "controllerType" is a class (CompanyService) rather than an interface (ICompanyService) it will always resolve to CompanyService. It would also explain why it errors when you try to

Resolve(controllerType,"2")

because what you're actually saying here is:

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

which doesn't exist.

This would also explain why it works when you call:

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

Because you're setting the correct interface here

So, short answer:

I think you're passing the concrete class type rather than the interface to Unity. Should be fairly easy to check.