StructureMap: как отправить контейнер в класс с конструктором, который не принимает параметры
Я пытаюсь выяснить, как я могу передать контейнер StructrueMap в класс, который я написал, который наследуется от другого (MS-Class).
namespace TheNamespace
{
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
/* **This can't be done**
public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager)
{
_someField= portalTenantManager;
}*/
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
//How does it work ???????????
var portalTenantManager = container.GetInstance<IPortalTenantManager>();
//Do something with the portalTenantManager
}
}
Мне нужно, чтобы portalTenantManager был экземпляром, который я определил в своем контейнере в Global.asax.
Мой Global Assax имеет следующие настройки:
protected void Application_Start()
{
var container = new Container();
container.Configure(x =>
{ ....
....
x.For<IPortalTenantManager>().Use<PortalTenantManager>();
});
...
...
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container));
...
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapApiControllerFactory(container);
...
}
Изменить: Из-за комментариев @NightOwl888 я объясню немного дальше, что делает этот класс. (Надеюсь, объяснить, почему мои руки связаны)
Мое приложение может аутентифицировать пользователя с помощью Azure Active Directory и поддерживает мультитенантность. В конвейере аутентификации у меня есть возможность сохранить конечные точки проверки в моей базе данных вместо способа по умолчанию в файле web.config. Посмотрите MSDN и это, что на самом деле объясняет, что именно я делаю.
Поэтому я зарегистрировал свой класс в web.config под тегом IssueNameRegistry. В какой-то момент конвейера проверки создается мой класс и вызывается переопределенный метод IsThumbprintValid. Проблема в том, что класс, зарегистрированный в isserNameRegistry, ожидает конструктор без параметров (вот он! Ограниченная конструкция!), Поэтому я не могу создать конструктор, который решит мою проблему.
Спасибо за вашу помощь
1 ответ
Оказывается, этот вопрос был задан ранее на MSDN, ответ на который был предоставлен Трэвисом Спенсером в 2 разных постах.
По моему опыту, типично иметь один контейнер и использовать его на стороне службы или в Интернете. При запуске службы или веб-приложения вы можете создать контейнер, зарегистрировать зависимости, создать новый экземпляр класса SecurityTokenServiceConfiguration, разрешить ваши зависимости, использовать его для создания объекта SecurityTokenService и разместить его.
После первой беты мы действительно настаивали на поддержке DI. Мы получили небольшую зацепку в бета-версии 2. Теперь вы можете создать собственный класс SecurityTokenServiceConfiguration, который переопределяет виртуальный метод CreateSecurityTokenService. Реализация в Microsoft SecurityTokenServiceConfiguration делает Activator.CreateInstance; ваш может сделать IoC. Это может включать разрешение IssuerNameRegistiry. Возможно, что-то вроде этого:
RequestSecurityTokenResponse Issue(IClaimsPrincipal principal, RequestSecurityToken request)
{
SecurityTokenServiceConfiguration config = new MyGoodSecurityTokenServiceConfiguration();
SecurityTokenService sts = config.CreateSecurityTokenService();
RequestSecurityTokenResponse rstr = sts.Issue(principal, request);
return rstr;
}
public class MyGoodSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
{
public override SecurityTokenService CreateSecurityTokenService()
{
IssuerNameRegistry = IoC.Resolve<IssuerNameRegistry>();
var sts = IoC.Reslove<SecurityTokenService>();
return sts;
}
}
Конечно, это означает, что вам нужно создать статический экземпляр вашего DI-контейнера, чтобы он был доступен для вашего SecurityTokenServiceConfiguration
учебный класс. Лично мне не нравится эта идея, потому что она делает ваш DI-контейнер доступным для всего приложения, что может привести к злоупотреблению DI-контейнером как локатором службы.
В идеале в любой дружественной к DI среде может быть способ передать контейнер в абстрактную фабрику для разрешения служебных зависимостей. Однако, поскольку я не знаком с WIF, неясно, можно ли это сделать - возможно, класс, где Issue
метод существует, может быть добавлен конструктор? Хитрость заключается в том, чтобы продолжать идти по цепочке, пока вы не найдете первое место в структуре, где вы можете вмешаться и выполнить всю свою конфигурацию DI там.