Разрешение именованной регистрации с использованием Unity 2 в DefaultControllerFactory
У меня есть проблема с разрешением именованных регистраций зарегистрированных типов в Unity 2 с использованием ASP.NET MVC 3 с DI, установленным в DefaultControllerFactory.
В одной сборке я определил контейнер 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 ответ
Container.Resolve(type,string)
а также
Container.Resolve<T>(string)
не разные методы.
Resolve (строка) на самом деле является методом расширения, который внутренне вызывает Container.Resolve(тип, строка).
Глядя на код, "controllerType" это класс или интерфейс? Если "controllerType" является классом (CompanyService), а не интерфейсом (ICompanyService), он всегда будет преобразован в CompanyService. Было бы также объяснить, почему это ошибки, когда вы пытаетесь
Resolve(controllerType,"2")
потому что вы на самом деле говорите:
container.Resolve(typeof(CompanyService),"2");
который не существует
Это также объясняет, почему это работает, когда вы звоните:
container.Resolve<ICompanyService>("2");
Потому что вы устанавливаете правильный интерфейс здесь
Итак, короткий ответ:
Я думаю, что вы передаете конкретный тип класса, а не интерфейс для Unity. Должно быть довольно легко проверить.