Setup Ninject for WCF [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
Does anyone have a clear instruction on how to setup Ninject in WCF? been googling around but I cant see any updated guidelines on how to use Ninject in WCF.

Using NInject with WCF is the same as using any other DI container. To do this you need to use 3 WCF extensibility points: InstanceProvider, ServiceHost and ServiceHostFactory.
The custom InstanceProvider will be used to create service instances by using a constructor with parameters. The code can be seen below.
public class NInjectInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IKernel kernel;
public NInjectInstanceProvider(IKernel kernel)
{
if (kernel == null) throw new ArgumentNullException("kernel");
this.kernel = kernel;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
//delegate to GetInstance(InstanceContext)
return GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
//resolve the service instance
return kernel.Get(instanceContext.Host.Description.ServiceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
kernel.Release(instance);
}
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)
{
}
}
This custom instance provider is then applied to every contract in the ServiceHost class. This is done by using a contract behavior. This is why the instance provider also implements IContractBehavior. You can see that we apply the instance provider in the ApplyDispatchBehavior method. The code below presents the ServiceHost and ServiceHostFactory implementations.
public class NInjectServiceHostFactory : ServiceHostFactory
{
private readonly IKernel kernel;
public NInjectServiceHostFactory()
{
kernel = new StandardKernel();
kernel.Bind<IDummyDependency>().To<DummyDepencency>();
//add the rest of the mappings here
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new NInjectServiceHost(kernel, serviceType, baseAddresses);
}
}
public class NInjectServiceHost : ServiceHost
{
public NInjectServiceHost(IKernel kernel, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (kernel == null) throw new ArgumentNullException("kernel");
foreach (var cd in ImplementedContracts.Values)
{
cd.Behaviors.Add(new NInjectInstanceProvider(kernel));
}
}
}
You can see that inside the ServiceHost constructor we iterate over all implemented contracts and apply the behavior we need. In our case this is NInjectInstanceProvider.
The custom ServiceHostFactory is required in order to create the DI container and populate it with mappings. We then override the CreateServiceHost method in order to provide our custom ServiceHost implementation.
The setup is complete at this point. All you need to do is create a WCF service that has a dependency on IDummyDependency. Also, don't forget to set the Factory attribute in the svc file like below (right click on svc file, then "View Markup"):
<%# ServiceHost Language="C#" Debug="true" Service="Service.DummyService" Factory="Service.NInjectServiceHostFactory" %>
Hope this helps. Also, I think NInject offers some implementations for this out of the box in NInject.Extensions.Wcf.dll.

Related

How to pass dependencies to a WCF restful service

I am new to Rest services. I did fair bit of research on this topic but still not clearly understood. Hope someone clear this to me. Thanks in advance.
My client is going to execute a method on my service class through an url. All I understood is client going to call
localhost/service/get/customers
In my rest service I have dependencies like a IRepository so that I can go to database and fetch the records. If I go with constructor injection when would client call this constructor?
It looks like I need to use a service locator to fetch IRepository inside the method which I need it.
Doesn't this violate OOP principle? Is testing easy without DI?
Can anyone please clarify this.
For any service how do we expect client to know what is IRepository is what methods it does have?
Is isn't it for internal implementation purpose Do we need t expose to the client? Why should he bother about it? Can't I provide just Uri Which method to call (localhost/service/Products) and job done.
I will appreciate if you provide any live example.
Thanks a lot.
No, it will not violate OOP priciple, if you will resolve for dependency inside a method. But there is no need for that, you can use constructor Dependency Injection within WCF using Instance Provider and ServiceHostFactory, there is also good example in this question.
If you are self-hosting the service, it will be even more simpler because it requires implementing only IInstanceProvider and ServiceHost. Assuming that you have Service service with constructor taking an IDependency parameter:
public class CustomInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dependency;
public CustomInstanceProvider(IDependency dependency)
{
this.dependency = dependency;
}
public object GetInstance(InstanceContext instanceContext)
{
// Here you are injecting dependency by constructor
return new Service(dependency);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
}
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(IDependency dependency, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new CustomInstanceProvider(dependency));
}
}
}
Then when creating service, use CustomServiceHost:
var serviceHost = new CustomServiceHost(dependency, typeof(Service), uris);

Dependency Injection for WCF Custom Behaviors

In my WCF service I have a custom message inspector for validating incoming messages as raw XML against an XML Schema. The message inspector has a few dependencies that it takes (such as a logger and the XML schema collection). My question is, can I use a Dependency Injection framework (I'm using Ninject at the moment) to instantiate these custom behaviours and automatically inject the dependencies?
I've made a simple example demonstrating the concept:
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Extensions.Logging;
public class LogMessageInspector : IDispatchMessageInspector
{
private readonly ILogger log;
public LogMessageInspector(ILogger log)
{
this.log = log;
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
LogMessage(ref request);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
LogMessage(ref reply);
}
private void LogMessage(ref Message message)
{
//... copy the message and log using this.log ...
}
}
public class LogMessageBehavior : IEndpointBehavior
{
private readonly IDispatchMessageInspector inspector;
public LogMessageBehavior(IDispatchMessageInspector inspector)
{
this.inspector = inspector;
}
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.inspector);
}
public void Validate(ServiceEndpoint endpoint) { }
}
How can I go about injecting an ILogger into LogMessageInspector and a LogMessageInspector into LogMessageBehavior?
Second question, is this overkill?
Edit: I can get this to work if I build my service in code because I create the behaviour using Ninject. However, when configuring the service via config, I need to add an additional class that extends BehaviorExtensionElement. This class is created by WCF and I can't seem to find a way to cause that to be created by Ninject instead. Configured in code:
static void Main(string[] args)
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IEchoService>().To<EchoService>();
kernel.Bind<LogMessageInspector>().ToSelf();
kernel.Bind<LogMessageBehavior>().ToSelf();
NinjectServiceHost<EchoService> host = kernel.Get<NinjectServiceHost<EchoService>>();
ServiceEndpoint endpoint = host.AddServiceEndpoint(
typeof(IEchoService),
new NetNamedPipeBinding(),
"net.pipe://localhost/EchoService"
);
endpoint.Behaviors.Add(kernel.Get<LogMessageBehavior>());
host.Open();
Console.WriteLine("Server started, press enter to exit");
Console.ReadLine();
}
}
This works fine, but I don't know how to create the behaviour when configured via my app.config:
<system.serviceModel>
<services>
<service name="Service.EchoService">
<endpoint address="net.pipe://localhost/EchoService"
binding="netNamedPipeBinding"
contract="Contracts.IEchoService"
behaviorConfiguration="LogBehaviour"
/>
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="logMessages" type="Service.LogMessagesExtensionElement, Service" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="LogBehaviour">
<logMessages />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
public class LogMessagesExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(LogMessageBehavior); }
}
protected override object CreateBehavior()
{
//how do I create an instance using the IoC container here?
}
}
How can I go about injecting an ILogger into LogMessageInspector and a
LogMessageInspector into LogMessageBehavior?
The approach has been described here
UPDATE
Please correct me if I'm wrong but I guess the question boils down to how could you get an instance of Ninject kernel in BehaviorExtensionElement.CreateBehavior? The answer depends on your hosting scenario. If hosted under IIS you could add something like this to your NinjectWebCommon:
public static StandardKernel Kernel
{
get { return (StandardKernel)bootstrapper.Kernel; }
}
Since you seem to be self-hosting, you might want to go for a static instance of the kernel too. In my view, however, this is not a terribly good idea.
I'd actually vote for your own approach and configure the behavior programmatically unless BehaviorExtensionElement is necessary because you need to be able to configure the behavior through the config file.
is this overkill?
It depends, but definitely not if you're going to unit test the implementation.
Instead of validation raw XML against an XML schema, why not take a more object oriented approach? You could for instance model each operation as a single message (a DTO) and hide the actual logic behind a generic interface. So instead of having a WCF service which contains a MoveCustomer(int customerId, Address address) method, there would be a MoveCustomerCommand { CustomerId, Address } class and the actual logic would be implemented by a class that implements the ICommandHandler<MoveCustomerCommand> interface with a single Handle(TCommand) method.
This design gives the following advantages:
Every operation in the system gets its own class (SRP)
Those message/command objects will get the WCF contract
The WCF service will contain just a single service class with a single method. This leads to a WCF service that is highly maintainable.
Allows adding cross-cutting concerns by implementing decorators for the ICommandHandler<T> interface (OCP)
Allows validation to be placed on the message/command objects (using attributes for instance) and allows this validation to be added again by using decorators.
When you apply a design based around a single generic ICommandHandler<TCommand> interface, its very easy to create generic decorators that can be applied to all implementations. Some decorators might only be needed to be applied when running inside a WCF service, others (like validation) might be needed for other application types as well.
A message could be defined as follows:
public class MoveCustomerCommand
{
[Range(1, Int32.MaxValue)]
public int CustomerId { get; set; }
[Required]
[ObjectValidator]
public Address NewAddress { get; set; }
}
This message defines an operation that will move the customer with CustomerId to the supplied NewAddress. The attributes define what state is valid. With this we can simply do object based validation using .NET DataAnnotations or Enterprise Library Validation Application Block. This is much nicer than having to write XSD based XML validations which are quite unmaintainable. And this is much nicer than having to do complex WCF configurations as you are currently trying to solve. And instead of baking this validation inside the WCF service, we can simply define a decorator class that ensures every command is validated as follows:
public class ValidationCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public ValidationCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
// Throws a ValidationException if invalid.
Validator.Validate(command);
this.decoratedHandler.Handle(command);
}
}
This ValidationCommandHandlerDecorator<T> decorator can be used by any type of application; not only WCF. Since WCF will by default not handle any thrown ValidationException, you might define a special decorator for WCF:
public class WcfFaultsCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public WcfFaultsCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
try
{
this.decoratedHandler.Handle(command);
}
catch (ValidationException ex)
{
// Allows WCF to communicate the validation
// exception back to the client.
throw new FaultException<ValidationResults>(
ex.ValidationResults);
}
}
}
Without using a DI container, a new command handler could be created as follows:
ICommandHandler<MoveCustomerCommand> handler =
new WcfFaultsCommandHandlerDecorator<MoveCustomerCommand>(
new ValidationCommandHandlerDecorator<MoveCustomerCommand>(
// the real thing
new MoveCustomerCommandHandler()
)
);
handler.Handle(command);
If you want to know more about this type of design, read the following articles:
Meanwhile... on the command side of my architecture
Writing Highly Maintainable WCF Services
Try having your LogMessageBehavior also use BehaviorExtensionElement as its base class, then you should be able to do the following:
public override Type BehaviorType
{
get { return this.GetType(); }
}
protected override object CreateBehavior()
{
return this;
}

When does WCF service host destroy custom IDispatchMessageInspector?

I have created a custom implementation of the IDispatchMessageInspector interface, and my code is working 99% fine.
My problem is that I need to free some managed objects when the WCF service host is killed and/or frees an instance of my class. My objects to free implement IDisposable but they aren't being disposed. I've been through the MSDN library (more confused) and the SO archives, but haven't found anything that addresses the question "When/where does a WCF service host destroy MessageInspectors?"
Do I need to hook an event someplace? Do I need to implement something even more arcane from the ServiceModel namespace?
Can anyone give me a pointer in the right direction?
Edit 1: Clarifications
At the moment, I am running in the IDE using the automatic webserver. I am not ultimately in control of the host once in production, could be any of the valid server host choices.
The MyCore.My and MyCore.MyProperties objects are the ones I am trying to dispose of when the WCF server host is killed/bounced.
Even when I have killed the webserver processes (those things in the Taskbar) the Dispose() is never called.
Edit 2: Code snippets added.
using /* snip */
using MyCore = Acme.My;
namespace My.SOAP
{
public class MyMessageInspector : IDispatchMessageInspector
{
protected static MyCore.My _My;
protected static MyCore.MyProperties _MyProps;
protected static ConcurrentDictionary<string, MyCore.AnotherSecretThing> _anotherSecretThings = new ConcurrentDictionary<string, MyCore.AnotherSecretThing>();
protected static void InitMy()
{
if (_My != null) return;
_MyProps = new MyCore.MyProperties();
MyCore.MySqlDatabaseLogger logger = new MyCore.MySqlDatabaseLogger(_MyProps);
_My = new MyCore.My(logger);
}
public MyMessageInspector()
{
InitMy();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
MyMessageHeader header = null;
try
{
// find My header
Int32 headerPosition = request.Headers.FindHeader(MyMessageHeaderKey.MyHeaderElementName, MyMessageHeaderKey.MyNamespace);
// get reader
XmlDictionaryReader reader = request.Headers.GetReaderAtHeader(headerPosition);
// get My header object
header = MyMessageHeader.ReadHeader(reader);
// add to incoming messages properties dictionary
OperationContext.Current.IncomingMessageProperties.Add(MyMessageHeaderKey.MyHeaderElementName, header);
}
catch (Exception ex)
{
// log via ExceptionHandlingBlock
}
MyCore.SecretThings SecretThings = CreateSecretThings(/* snip */);
return SecretThings.Id;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
MyCore.SecretThings req = _My.GetSecretThingsOnThread();
// if we didn't find the SecretThings, there is nothing to stop() and no data to put in the MessageHeaders
if (req == null) return;
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
var MyHeader = new MyMessageHeader(/* snip */);
reply.Headers.Add(MyHeader);
req.Stop(MyCore.Status.SUCCESS);
}
protected MyCore.SecretThings CreateSecretThings(string key, Dictionary<string, string> ids)
{
/* snip */
return _My.GetSecretThings(/* snip */);
}
}
}
I've been having a look at the DispatchMessageInspector and how it is implemented.
As you probably know you register your MessageInspectors with an IEndpointBehavior (adding endpoint behaviours through configuration or code). You create an instance of your DispatchMessageInspector within the EndpointBehaviour.
public class MyBehaviour : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint,
System.ServiceModel.Channels.BindingParameterCollection
bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
var inspector = new SampleMessageInspector(); //register
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
According to http://msdn.microsoft.com/en-us/magazine/cc163302.aspx Endpoint behaviours are registered by the Service Host
These behavior collections are automatically populated during the ServiceHost and ChannelFactory construction process with any behaviors that are found in your code (via attributes) or within the configuration file (more on this shortly). You can also add behaviors to these collections manually after construction. The following example shows how to add the ConsoleMessageTracing to the host as a service behavior:
ServiceHost host = new ServiceHost(typeof(ZipCodeService));
host.Description.Behaviors.Add(new ConsoleMessageTracing());
And further dictates that the ServiceHost has a lifetime as long as the service...
ServiceHost extension objects remain in memory for the lifetime of the ServiceHost while InstanceContext and OperationContext extension objects only remain in memory for the lifetime of the service instance or operation invocation. Your custom dispatcher/proxy extensions can use these collections to store (and look up) user-defined state throughout the pipeline.
I'm assuming this is why your objects within your MessageInspectors are never being destroyed.
Some would see it as an anti-pattern but I would possibly recommend a ServiceLocator that your MessageInspectors can use to retrieve objects. You could then look at setting their lifetime as long as its parent usage?
public class SampleMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
var objectToDispose = ServiceLocator.Current.GetInstance<ObjectToDispose>();
//do your work
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//do some other work
}
}
To follow on from what i've mentioned...
As an example this post mentions using Ninject as the IoC container and set the life time of your objects as the lifetime of the WCF service
Bind(...).To(...).InScope(() => OperationContext.Current)
Ninject WCF Garbage Collection on repositories
You could then get access to the Ninject Kernal through the ServiceLocator and the objects (_MyProperties etc...) would be disposed off

Ninject - Creating a Custom NinjectWebServiceHost

I have a couple web services in my WCF project that require a custom ServiceAuthorizationManager to be able to authenticate OAuth calls. To do this, I created a custom WebServiceHostFactory. I am in the process of wiring up Ninject and am having a difficult time getting this converted over to a NinjectWebServiceHostFactory. Here is my code:
public class MyServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
public class MyServiceHost: WebServiceHost
{
public MyServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
}
}
When I switch the WebServiceHost to a NinjectWebServiceHost it asks for an IServiceBehavior implementation. I have a ServiceBehavior attribute on my web service and I have a ServiceBehavior section in my web.config.
Has anyone seen this and been able to successfully implement something like this? Is there a better route to wire this up for my 2 web services? I do not want this to affect all of my web services.
We just did this the other day. We found it easier to implement a new type of NinjectWebServiceHostFactory that wired up the custom AuthorizationManager for us.
public class OAuthHostFactory : NinjectWebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
host.Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
return host;
}
}
This gives us the flexibility to pick and choose which routes or svc's we want to implement this particular factory on.
I believe you'll have to create a custom attribute which implements the IServiceBehavior interface yourself.
You're ApplyDispatchBehavior method implementation will want to look something like this:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
Type serviceType = serviceDescription.ServiceType;
IInstanceProvider instanceProvider = new NinjectInstanceProvider(
new StandardKernel(), serviceType);
foreach(ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
Basically, you're creating a custom IInstanceProvider interface implementation which depends on Ninject to create instances for the DispatchRuntime.
Peter De Rycke goes into it further in his blog entry "Using an IoC container to create WCF service instances" (note the code above was taken from there).
I imagine if you still want to use a NinjectWebServiceHost, you could pass an IServiceBehavior implementation much like the one Peter outlines above.

Providing a factory instead of a Type in WCF ServiceHost

Is there any way to extend ServiceHost so that it accepts a factory?
I would like to use dynamic service proxies for some preprocessing of WCF calls without touching the service implementation.
EDIT
Now the ServiceHost creation looks like
var host = new ServiceHost(typeof(MyService));
and i would like to use something like
var factory = new ServiceProxyFactory<MyService>();
var host = new MyServiceHost(typeof(MyService), factory);
The interface i was looking for is IInstanceProvider.
public class MyServiceInstanceProvider<TService> : IInstanceProvider where TService : new()
{
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return ServiceFactory.Create<TService>();
}
public object GetInstance(InstanceContext instanceContext)
{
return ServiceFactory.Create<TService>();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
return;
}
}
public class MyEndpointBehavior<TService> : IEndpointBehavior where TService : new()
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new MyServiceInstanceProvider<TService>();
}
public void Validate(ServiceEndpoint endpoint)
{
return;
}
}
public class MyServiceHost<TService> : ServiceHost where TService : new()
{
public MyServiceHost(params Uri[] baseAddresses)
:base(typeof(TService), baseAddresses)
{
}
public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
{
var endpoints = base.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
return endpoints;
}
public override void AddServiceEndpoint(ServiceEndpoint endpoint)
{
base.AddServiceEndpoint(endpoint);
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
}
What you describe is not really possible with .NET...
You can implement a custom ServiceHost which allows you to customize the behaviour of the ServiceHost and/or the IDispatchMessageInspector which allows you inspect/modify any message inbound and outbound... IF you really wnat to implement some sort of "dynamic routing" then there is always the Routing capability of WCF...
Other options (though no 100% solution):
WCF service returning another service (service factory?)
WCF and factory design pattern
http://msdn.microsoft.com/en-us/library/aa702697.aspx
EDIT - I stand corrected:
It is not really possible to use a usual Factory BUT WCF provides the possibility to plug in an IInstanceProvider either at the Service or the Endpoint level...
For further reference see the following links
http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx
http://msdn.microsoft.com/library/system.servicemodel.dispatcher.iinstanceprovider.aspx
How do I pass values to the constructor on my wcf service?
http://geekswithblogs.net/13DaysaWeek/archive/2010/12/01/dependency-injection-and-wcf-services.aspx
http://www.eggheadcafe.com/tutorials/aspnet/b428fb65-08b4-45c8-97cd-47ee1a1eaf41/composing-wcf-applications.aspx

Categories