Is it possible to instantiate a WebServiceHost via an instance of the service type, without a parameterless constructor? - wcf

I am trying to create self-hosted System.ServiceModel.Web.WebServiceHost (.NET 4), however I am running into an issue with the constructor. There are three options:
WebServiceHost() a parameterless constructor that seems pointless, as there's no way to specify the type of the service, or even the contract. Reflecting on it, it doesn't do anything- just an empty default constructor that doesn't call base.
WebServiceHost(object singletonInstance, params Uri[] baseAddresses) I don't want a singleton instance, as this is a InstanceContextMode.PerCall class.
WebServiceHost(System.Type serviceType, params Uri[] baseAddresses) The type I want to instantiate as a service doesn't have a parameterless constructor (which is a requirement of this method). I'm using NInject to push the parameters into the constructor. However, I'm trying to run this as a self-hosted test, so I want to avoid DI.
Are there any options along these lines, or will I have to not self-host?

To support service classes without parameter-less constructors you need to use an IInstanceProvider implementation which knows how to create the service class. The code below shows one with the WebServiceHost, and you can find more about instance providers at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx.
public class StackOverflow_9997163
{
[ServiceContract]
public class Service
{
private int increment;
public Service(int increment)
{
this.increment = increment;
}
[WebGet]
public int Add(int x, int y)
{
return x + y + increment;
}
}
class MyInstanceProvider : IInstanceProvider
{
Func<Service> serviceCreator;
public MyInstanceProvider(Func<Service> serviceCreator)
{
this.serviceCreator = serviceCreator;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.serviceCreator();
}
public object GetInstance(InstanceContext instanceContext)
{
return this.serviceCreator();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
class MyServiceBehavior : IServiceBehavior
{
Func<Service> serviceCreator;
public MyServiceBehavior(Func<Service> serviceCreator)
{
this.serviceCreator = serviceCreator;
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = new MyInstanceProvider(this.serviceCreator);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
int currentIncrement = 1;
host.Description.Behaviors.Add(new MyServiceBehavior(delegate()
{
return new Service(currentIncrement++);
}));
host.Open();
Console.WriteLine("Host opened");
for (int i = 0; i < 10; i++)
{
WebClient c = new WebClient();
Console.WriteLine(c.DownloadString(baseAddress + "/Add?x=6&y=8"));
}
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Related

Why is WCF discovery not working with custom service factory host in WCF?

I have created a custom ServiceHostFactory, a ServiceHost, a ServiceBehavior and a ServiceInstanceProvider for DI using unity in my IIS hosted WCF service.
After this UDP discovery has stopped working. How is the ServiceDiscovery behavior created by WCF? Where is the UDPDiscoveryEndpoint created? Am I overriding some behavior in the code below?
public class ServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
{
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new ServiceHost(serviceType, baseAddresses);
}
}
public class ServiceHost : System.ServiceModel.ServiceHost
{ ....
protected override void OnOpen(TimeSpan timeout)
{
Description.Behaviors.Add(new ServiceBehavior());
base.OnOpen(timeout);
}
}
public class ServiceBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
var cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = new ServiceInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
}
public class ServiceInstanceProvider : IInstanceProvider
{...
public object GetInstance(InstanceContext instanceContext, Message message)
{
return Container.Instance.Resolve(_serviceType);
}
}

IClientMessageInspector detect one-way operation

I need to do some operation logging in IClientMessageInspector and knowning when an operation has started and ended is vital. I can't however get AfterReceiveReply for one-way operations which is clear why. Is there a way to know that an operation is one-way in BeforeSendRequest overload so I could just ignore it?
There's no information on the inspector itself (or the message passed to BeforeSendRequest), but you can pass this information to the inspector, and use the message action to see whether the operation is one way or not.
public class StackOverflow_10354828
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string Echo(string text);
[OperationContract(IsOneWay = true)]
void Process(string input);
}
public class Service : ITest
{
public string Echo(string text)
{
return text;
}
public void Process(string input) { }
}
class MyInspector : IClientMessageInspector
{
public HashSet<string> oneWayActions;
public MyInspector(ServiceEndpoint endpoint)
{
this.oneWayActions = new HashSet<string>();
foreach (var operation in endpoint.Contract.Operations)
{
if (operation.IsOneWay)
{
oneWayActions.Add(operation.Messages[0].Action);
}
}
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
Console.WriteLine("In AfterReceiveReply");
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
Console.WriteLine("In BeginSendRequest");
if (this.oneWayActions.Contains(request.Headers.Action))
{
Console.WriteLine("This is a one-way operation");
}
return null;
}
}
class MyBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MyInspector(endpoint));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
factory.Endpoint.Behaviors.Add(new MyBehavior());
ITest proxy = factory.CreateChannel();
proxy.Echo("Hello");
Console.WriteLine();
proxy.Process("world");
Console.WriteLine();
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
Replying to myself, a the moment I'm doing this:
bool isOneWay = request.Headers.ReplyTo == null;

Enabling SOAP Message Inspection for a Single Operation

How can I force an IMessageInspector to fire only when a specific operation is called, rather than firing whenever a call to the service is made? Currently, I am applying a custom IEndpointBehavior to the endpoint which calls this IMessageInspector, but this is not exactly what I would like to do...
The message inspectors are bound to the dispatch runtime object, which is a single one for each endpoint, not operation. If a parameter inspector works, then you can use it (it's bound to the operation), but if you need a message inspector, then it cannot be bound to a single operation. But you can, inside your inspector, check whether the operation is what you expect (based on the Action header, which is unique per operation), as shown in the code below.
public class StackOverflow_7502134
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string Echo(string text);
[OperationContract]
int Add(int x, int y);
}
public class Service : ITest
{
public string Echo(string text)
{
return text;
}
public int Add(int x, int y)
{
return x + y;
}
}
public class MyInspector : IEndpointBehavior, IDispatchMessageInspector
{
string[] operationNames;
public MyInspector(params string[] operationNames)
{
this.operationNames = operationNames ?? new string[0];
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void Validate(ServiceEndpoint endpoint)
{
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// by default, action == <serviceContractNamespace>/<serviceContractName>/<operationName>
string operationName = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf('/') + 1);
if (this.operationNames.Contains(operationName))
{
Console.WriteLine("Inspecting request to operation {0}", operationName);
Console.WriteLine(request);
Console.WriteLine();
return operationName;
}
else
{
return null;
}
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
string operationName = correlationState as string;
if (operationName != null)
{
Console.WriteLine("Inspecting reply from operation {0}", operationName);
Console.WriteLine(reply);
Console.WriteLine();
}
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
MyInspector inspector = new MyInspector("Add"); // inspecting Add, not Echo
host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "").Behaviors.Add(inspector);
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine("Calling Echo");
Console.WriteLine(proxy.Echo("Hello world"));
Console.WriteLine();
Console.WriteLine("Calling Add");
Console.WriteLine(proxy.Add(4, 5));
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

WCF and Unity: Set up InstanceProvider, ServiceBehaviour, -Host, -Factory... Now what?

I have been looking for a way to use Unity for Dependency Injection in my WCF service. I have been trying to understand the code described in these two blogs, which is quite similar:
Integrating Unity with WCF
WCF and Unity 2.0
So I added this code to a separate project in my solution and refer to the custom servicehostfactory in a SVC file to my WFC service (separate project).
The question is now: How do I access the objects in my container from my WCF Service methods?
EDIT
These are my implementations:
ServiceHostFactory...
namespace UnityWcfAssembler
{
public class UnityServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
UnityServiceHost serviceHost = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer container = new UnityContainer();
serviceHost.Container = container;
//TODO configuration from app.config
//configure container
//UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
//section.Configure(serviceHost.Container);
InitializeSessionFactories(container);
return serviceHost;
}
private static void InitializeSessionFactories(UnityContainer container)
{
Dictionary<String, ISessionFactory> sessions = new Dictionary<string, ISessionFactory>();
Configuration Cfg = new Configuration();
Cfg.Configure();
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=Fossils;Integrated Security=true;");
ISessionFactory Factory = Cfg.BuildSessionFactory();
sessions.Add("fossils", Factory);
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=TypeCollection;Integrated Security=true;");
ISessionFactory typeFactory = Cfg.BuildSessionFactory();
sessions.Add("type", typeFactory);
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=PersonalCollection;Integrated Security=true;");
ISessionFactory persFactory = Cfg.BuildSessionFactory();
sessions.Add("personal", persFactory);
container.RegisterInstance(sessions);
}
}
}
ServiceHost...
namespace UnityWcfAssembler
{
public class UnityServiceHost : ServiceHost
{
public UnityContainer Container { get; set; }
public UnityServiceHost()
{
Container = new UnityContainer();
}
public UnityServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses)
{
Container = new UnityContainer();
}
protected override void OnOpening()
{
new UnityServiceBehavior(Container).AddToHost(this);
base.OnOpening();
if (Description.Behaviors.Find<UnityServiceBehavior>() == null)
Description.Behaviors.Add(new UnityServiceBehavior(Container));
}
}
}
InstanceProvider...
namespace UnityWcfAssembler
{
public class UnityInstanceProvider : IInstanceProvider
{
public UnityContainer Container { set; get; }
public Type ServiceType { set; get; }
public UnityInstanceProvider() : this(null)
{
}
public UnityInstanceProvider(Type type)
{
ServiceType = type;
Container = new UnityContainer();
}
// Get Service instace via unity container
public object GetInstance(InstanceContext instanceContext, Message message)
{
return Container.Resolve(ServiceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
}
IServiceBehavior...
namespace UnityWcfAssembler
{
public class UnityServiceBehavior : IServiceBehavior
{
public UnityInstanceProvider InstanceProvider { get; set; }
private ServiceHost serviceHost;
public UnityServiceBehavior()
{
InstanceProvider = new UnityInstanceProvider();
}
public UnityServiceBehavior(UnityContainer unity)
{
InstanceProvider = new UnityInstanceProvider();
InstanceProvider.Container = unity;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
InstanceProvider.ServiceType = serviceDescription.ServiceType;
ed.DispatchRuntime.InstanceProvider = InstanceProvider;
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
public void AddToHost(ServiceHost host)
{
// only add to host once
if (serviceHost != null) return;
host.Description.Behaviors.Add(this);
serviceHost = host;
}
}
}
Wcf Service...
namespace FossilsWcfService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class FossilsService : IFossilsService
{
private readonly Dictionary<string, ISessionFactory> sessionFactories;
public FossilsService(Dictionary<string, ISessionFactory> s)
{
sessionFactories = s;
}
public SpeciesList GetAllSpecies()
{
SpeciesList list = new SpeciesList();
ISessionFactory factory = sessionFactories["fossils"];
if(factory == null)
{
list.Species.Add(new FossilSpecies { GenusName = "Session factory could not be resolved from container!" });
return list;
}
ISession session = factory.OpenSession();
SpeciesManager speciesManager = new SpeciesManager(session);
IList<FossilSpecies> species = speciesManager.GetAllSpecies();
foreach (FossilSpecies fossilSpecies in species)
{
list.Species.Add(fossilSpecies);
}
return list;
}
FossilsWcfService.svc...
<%# ServiceHost Language="C#" Debug="true"
Service="Server.Services.ExampleService"
Factory="UnityWcfAssembler.UnityServiceHostFactory" %>
Should the latter have a different filename perhaps?
Now that you have the factory working, you should create a property with the interface, and declare the constructor and Unity will do the rest
public class InvoiceService : IInvoiceService {
private IPayService payService;
public IPayService PayService
{
get { return payService; }
set { payService= value; }
}
public InvoiceService(IPayService provider)
{
this.payService= provider;
}
public bool Pay(){
return PayService.Pay();
}
}
My Service Factory Implementaion
public class InvoiceFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
UnityServiceHost host = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer unity = new UnityContainer();
host.Container = unity;
//I'm doing it like this because I put some AOP in the service injected
var clazz = Intercept.ThroughProxy<IPayService>(new PayServiceConcreteClass(),
new InterfaceInterceptor(), new[] { new LoggingInjection() });
unity.RegisterType<IPayService>().RegisterInstance(clazz);
return host;
}
}
EDIT after code in the question
I'm not really sure what could be wrong, but I spot two things that I'm not sure about:
ServiceHostFactory...
//Better as an Interface
IDictionary<String, ISessionFactory> sessions = new Dictionary<string, ISessionFactory>();
//container.RegisterInstance(sessions);
//Registering the type not the class
container.RegisterType<IDictionary<String, ISessionFactory>>().RegisterInstance(sessions);
Wcf Service...
private readonly IDictionary<string, ISessionFactory> sessionFactories;
public FossilsService(IDictionary<string, ISessionFactory> s)
{
sessionFactories = s;
}
FossilsWcfService.svc
It's not missing the codebehind attribute? something like this
<%# ServiceHost Language="C#" Debug="true" Factory="InvoiceFactory" Service="InvoiceService" CodeBehind="InvoiceService.svc.cs" %>
...

Using Unity Dependency Injection with WCF services

I have the following after doing some research on other questions:
MyServiceHost:
public class MyServiceHost : ServiceHost
{
public MyServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new DependencyInjectionInstanceProvider(container));
}
}
}
DependencyInjectionInstanceProvider:
public class DependencyInjectionInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IUnityContainer container;
public DependencyInjectionInstanceProvider(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
var serviceType = instanceContext.Host.Description.ServiceType;
return this.container.Resolve(serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
this.container.Teardown(instance);
}
#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:
public class MyServiceHostFactory : ServiceHostFactory
{
private readonly IUnityContainer container;
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(this.container, serviceType, baseAddresses);
}
}
Email Service with an attempted Constructor Injection:
public class EmailValidator : IEmailValidator
{
private IFakeDAL fakeDAL;
public EmailValidator(IFakeDAL fakeDAL)
{
this.fakeDAL = fakeDAL;
}
public bool ValidateAddress(string emailAddress)
{
Console.WriteLine("Validating: {0}", emailAddress);
string pattern = #"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$";
return Regex.IsMatch(emailAddress, pattern);
}
}
My Console Host to start the Service:
static void Main(string[] args)
{
Type serviceType = typeof(EmailValidator);
Uri serviceUri = new Uri("http://localhost:8080/");
MyServiceHostFactory shf = new MyServiceHostFactory();
ServiceHost host = shf.CreateServiceHost(serviceType, serviceUri);
//ServiceHost host = new ServiceHost(serviceType, serviceUri);
host.Open();
My problem resides in the console host logic. The CreateServiceHost call has a syntax error due to the first argument expecting a Constructor string and not a Type. Which I don't understand since it does accept a Type parameter. In addition to that I don't understand where I should be mapping IFakeDAL to a concrete class. Can I do that in an app.config file or should I register that somewhere else?
ServiceHostFactory is for hosting in IIS. In self hosting you should use your derived ServiceHost directly. Here you have whole example including Unity configuration.
I´m using the following classes in my windows service to create WCF services and inject dependencies to it using unity.
UnityInstanceProvider:
internal class UnityInstanceProvider : IInstanceProvider {
private readonly IUnityContainer container;
private readonly Type contractType;
public UnityInstanceProvider(IUnityContainer container, Type contractType) {
this.container = container;
this.contractType = contractType;
}
public object GetInstance(InstanceContext instanceContext) {
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message) {
return container.Resolve(contractType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance) {
container.Teardown(instance);
}
}
UnityServiceBehavior:
public class UnityServiceBehavior : IServiceBehavior {
private readonly IUnityContainer container;
public UnityServiceBehavior(IUnityContainer container) {
this.container = container;
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) {
if (endpointDispatcher.ContractName != "IMetadataExchange") {
string contractName = endpointDispatcher.ContractName;
ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType);
}
}
}
}
}
UnityServiceHost:
public class UnityServiceHost : ServiceHost {
private IUnityContainer unityContainer;
public UnityServiceHost(IUnityContainer unityContainer, Type serviceType)
: base(serviceType) {
this.unityContainer = unityContainer;
}
protected override void OnOpening() {
base.OnOpening();
if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null) {
this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer));
}
}
}
With this classes you can do the following (The configuration of services is done in .config):
UnityContainer container = new UnityContainer();
UnityServiceHost serviceHost = new UnityServiceHost(container, typeof("Type of Service to host"));
serviceHost.Open();
The CreateServiceHost method expects an array of Uri instances, so try this instead:
ServiceHost host = shf.CreateServiceHost(serviceType, new[] { serviceUri });
You can map interfaces to types in either XML or code, but I'd recommend code, since XML has too high a maintenance overhead.
The Main method is an excellent Composition Root, but if you want to configure the container at that level, you'll need to pass it from the Main method to MyServiceHostFactory - which is perfectly fine when you host the service in a console application, but will not work if you want to host it in IIS, where MyServiceHostFactory should be the Composition Root, since IIS requires a default constructor.