Reputation: 12441
When I new a WCF service in my solution, can I do the following, have a constructor with parameter to pass in? If yes, how, when and where does the runtime fill in my required IBusinessLogic object?
[ServiceContract]
public interface IServiceContract
{
[OperationContract]
...
}
public class MyService : IServiceContract
{
IBusinessLogic _businessLogic;
public ServiceLayer(IBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
...
}
Upvotes: 42
Views: 45700
Reputation: 4761
I paraphrased @Mark Seemann's solution as a generic instance provider behavior.
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
}
Upvotes: 4
Reputation: 5357
Another case, in addition to the other responses, is when creating singleton service - this is when you pass an instance of your service to the ServiceHost (as opposed to a type);
Obviously as you create the instance you can use whichever constructor;
This approach will require adding an attribute to your service: [ServiceBehavior(InstanceContextMode.Single)];
Upvotes: 4
Reputation: 119806
Out of the box WCF will only use the default constructor, you can't use parameterised constructors. You have to do a bit of extra work to make WCF call parameterised constructors.
You could try this:
Upvotes: 13
Reputation:
You have to implement IInstanceProvider to be able to call a parametrized service constructor. Of this constructor will not be available in the generated proxy.
Upvotes: 2
Reputation: 4890
You can get WCF to (sort of indirectly) call non default constructors, for that to work you need to roll your own instance provider. You would need to implement IInstanceProvider and add a custom Service Behavior. Some links that will show you how to do this in combination with Spring.NET:
WCF Service Dependency Injection
Code example WCF Service Dependency Injection
Upvotes: 6