Lorsque je crée un service WCF dans ma solution, puis-je faire ce qui suit, avoir un constructeur avec un paramètre à transmettre? Si oui, comment, quand et où le runtime remplit-il mon objet IBusinessLogic requis?
[ServiceContract]
public interface IServiceContract
{
[OperationContract]
...
}
public class MyService : IServiceContract
{
IBusinessLogic _businessLogic;
public ServiceLayer(IBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
...
}
Par défaut, WCF n'utilisera que le constructeur par défaut, vous ne pouvez pas utiliser de constructeurs paramétrés. Vous devez faire un peu de travail supplémentaire pour créer des constructeurs paramétrés d'appel WCF.
Vous pouvez essayer ceci:
Comment passer des valeurs au constructeur sur mon service wcf?
Vous pouvez demander à WCF d'appeler (en quelque sorte indirectement) des constructeurs non par défaut, pour que cela fonctionne, vous devez rouler votre propre fournisseur d'instance. Vous devez implémenter IInstanceProvider et ajouter un comportement de service personnalisé. Quelques liens qui vous montreront comment procéder en combinaison avec Spring.NET:
Regardez ServiceHostFactory .
Un autre cas, en plus des autres réponses, est lors de la création d'un service singleton - c'est lorsque vous passez une instance de votre service au ServiceHost (par opposition à un type);
Évidemment, lorsque vous créez l'instance, vous pouvez utiliser n'importe quel constructeur;
Cette approche nécessitera l'ajout d'un attribut à votre service: [ServiceBehavior (InstanceContextMode.Single)];
J'ai paraphrasé la solution de @Mark Seemann comme comportement du fournisseur d'instance générique.
var Host = new ServiceHost(typeof(MyService), baseAddress);
var instanceProvider = new InstanceProviderBehavior<T>(() => new MyService(businessLogic));
instanceProvider.AddToAllContracts(Host);
public class InstanceProviderBehavior<T> : IInstanceProvider, IContractBehavior
where T : class
{
private readonly Func<T> m_instanceProvider;
public InstanceProviderBehavior(Func<T> instanceProvider)
{
m_instanceProvider = instanceProvider;
}
// I think this method is more suitable to be an extension method of ServiceHost.
// I put it here in order to simplify the code.
public void AddToAllContracts(ServiceHost serviceHost)
{
foreach (var endpoint in serviceHost.Description.Endpoints)
{
endpoint.Contract.Behaviors.Add(this);
}
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
// Create a new instance of T
return m_instanceProvider.Invoke();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
try
{
var disposable = instance as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
catch { }
}
#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
}
Vous devez implémenter IInstanceProvider pour pouvoir appeler un constructeur de service paramétré. De ce constructeur ne sera pas disponible dans le proxy généré.