问题
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.
来源:https://stackoverflow.com/questions/10918532/resolving-named-registration-using-unity-2-in-defaultcontrollerfactory