Я хотел бы передать значения в конструктора на классе, который реализует мой сервис.
Однако ServiceHost только позволяет мне передать от имени типа для создания, не что аргументы передать его contrstructor.
Я хотел бы смочь передать на фабрике, которая создает мой объект службы.
Что я нашел до сих пор:
Вам нужно будет реализовать комбинацию пользовательских ServiceHostFactory
, ServiceHost
и IInstanceProvider
.
Для службы с этой сигнатурой конструктора:
public MyService(IDependency dep)
Вот пример, который может развернуть MyService:
public class MyServiceHostFactory : ServiceHostFactory
{
private readonly IDependency dep;
public MyServiceHostFactory()
{
this.dep = new MyClass();
}
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
return new MyServiceHost(this.dep, serviceType, baseAddresses);
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(IDependency dep, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new MyInstanceProvider(dep));
}
}
}
public class MyInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dep;
public MyInstanceProvider(IDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
return new MyService(this.dep);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
var disposable = instance as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
#endregion
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
#endregion
}
Зарегистрируйте MyServiceHostFactory в файле MyService.svc или используйте MyServiceHost непосредственно в коде для сценариев самостоятельного размещения.
Вы можете легко обобщить этот подход, и на самом деле некоторые контейнеры DI уже сделали это за вас (подсказка: Windsor's WCF Facility).
Ответ Марка с помощью IInstanceProvider
правильный.
Вместо использования настраиваемой фабрики ServiceHostFactory можно также использовать настраиваемый атрибут (например, MyInstanceProviderBehaviorAttribute
). Получите его из атрибута
, сделайте так, чтобы он реализовал IServiceBehavior
и реализовал метод IServiceBehavior.ApplyDispatchBehavior
, например
// YourInstanceProvider implements IInstanceProvider
var instanceProvider = new YourInstanceProvider(<yourargs>);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (var epDispatcher in dispatcher.Endpoints)
{
// this registers your custom IInstanceProvider
epDispatcher.DispatchRuntime.InstanceProvider = instanceProvider;
}
}
Затем примените атрибут к классу реализации службы
[ServiceBehavior]
[MyInstanceProviderBehavior(<params as you want>)]
public class MyService : IMyContract
] Третий вариант: вы также можете применить поведение службы с помощью файла конфигурации.