Как вставить объект в класс валидатора WCF
После использования инъекции зависимостей для служб WCF существует ли способ использования DI для валидаторов WCF, чтобы можно было это сделать:
public class DIValidator : UserNamePasswordValidator
{
private readonly IService service;
[Inject]
public DIValidator(IService service)
{
this.service = service;
}
public override void Validate(string userName, string password)
{
service.Login(userName, password);
}
}
EDIT - я попытался применить совет Dzmitry к своему пользовательскому расширению поведения, поскольку мой валидатор определен в app.config. К сожалению, я получаю MethodMissingException, так как wcf хочет, чтобы мой валидатор имел конструктор по умолчанию:
System.MissingMethodException: No default constructor has been defined for this object.
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean
noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
Вот мой класс поведения:
public class DependencyInjectionServiceBehavior : BehaviorExtensionElement, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
serviceHostBase.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = DISupport.Kernel.Get<IService>();
}
}
Ответы
Ответ 1
В общем пользовательский валидатор назначается программно (есть также возможность сделать это из файла конфигурации), что-то вроде этого, и оно выполняется непосредственно перед тем, как открывается хост-узел, и в основном это также время, когда вы создаете экземпляр контейнера DI, который будет далее использоваться для обслуживания экземпляров через поставщика экземпляров:
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new LocalUserNamePasswordValidator();
Вы также можете использовать контейнер DI, чтобы создать свой собственный валидатор.
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = unityContainer.Resolve<UserNamePasswordValidator>();
Ответ 2
Я знаю, что это не то решение, которое вы ищете, но я бы создал конструктор по умолчанию, который получит IService из вашего контейнера IoC (локатор сервисов вместо DI). Не самый приятный способ сделать это, но самое простое, о котором я могу думать.
Изменить: вы можете оставить конструктор, который позволяет вам вводить зависимость, если вам нужно высмеять IService для тестирования или любой другой purpouse.