I'm trying to hock up WCF with dependency injection. All the examples that I have found is based on the assumptions that you either uses a .svc (ServiceHostFactory) service or uses app.config to configure the container. Other examples is also based on that the container is passed around to the classes.
I would like a solution where the container is not passed around (not tightly coupled to Unity). Where I don't uses a config file to configure the container and where I use self-hosted services.
The problem is - as I see it - that the ServiceHost is taking the type of the service implementation as a parameter so what different does it do to use the InstanceProvider?
The solution I have come up with at the moment is to register the ServiceHost (or a specialization) an register a Type with a name ( e.g. container.RegisterInstance<Type>("ServiceName", typeof(Service);).
And then container.RegisterType<UnityServiceHost>(new InjectionConstructor(new ResolvedParameter<Type>("ServiceName"))); to register the ServiceHost.
Any better solutions out there? I'm I perhaps way of in my assumptions.
Best regards,
Michael
Use Constructor Injection to wire up your service implementation, just like you would with any other class.
Here's a writeup on how to make WCF understand Constructor Injection.
The example in that answer demonstrates Poor Man's Injection, but you can extrapolate from it and set up your UnityContainer instance in the ServiceHostFactory instead of a hard-coded dependency.
You pass the container instance all the way to the custom IInstanceProvider. Now you can use the container in the GetInstance method:
public object GetInstance(InstanceContext instanceContext)
{
var serviceType = instanceContext.Host.Description.ServiceType;
return this.container.Resolve(serviceType);
}
Related
Looking on different libraries and even Microsoft code I've noticed two different ways of configuring options in code:
in ConfigureServices it can be done when registering DependencyInjection:
services.AddMvc(options => { });
or in Configure
app.UseStaticFiles(
new StaticFileOptions
{
ServeUnknownFileTypes = true
});
I tried to find out, which way use for which purpose and still don't know, assuming that creating your own middleware and registering both DI and usage.
Interesting issue you have found.
Looking into the source code i have found the following:
All the middleware registrations are an overload of this UseMiddleware function, which is an overload of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);.
In these overloads you can specify hard your own parameters for the middle-ware. Say you have a few strings in the constructor, the DI container will not be able to resolve this.
If the parameters aren't set though, it does fallback to the IServiceProvider to resolve the specific type. see extension class: Microsoft.Extensions.Internal.ActivatorUtilities (inside: Microsoft.AspNetCore.Http.Abstractions.dll)
Tips
As for best practice think about the following (my opinion though):
Try to avoid using simple types in constructor but use an Options class.
for IOptions use services.Configure<>() as here you can specify options from a ConfigSection => appsettings.
As for Services: be aware that middleware is a singleton! so adding a transient Service, will only be resolved once for this middleware!
I think best practise is to: Register Middleware AND its dependencies as singletons in IOC on startup. then resolve it yourself and add it yourself with the method App.Use([yourDelegate]).
The advantage of this method is it is easilier understandable than use the hidden microsoft code + Microsoft recently published an upgrade to the DI container to check if the scopes of your registrations match properly (and warn you if not).
This tool basically does: it checks if a dependency of a service has a smaller scope then the service itself: say service is scope: Singleton and the dependency is scope Transient. this means that if Singleton is resolved Transient is also resolved for this singleton and thus not resolved again on next usage of this singleton. (so its a hidden singleton usage).
within our per-session WCF services hosted in ISS, we would like to use Ninject to IOC different data access component through the interface.
Where would be the best place to declare the binding once? is it in Application_Start of Global.asax?
If it is, how could I obtain the instance through the inferface from Ninject?
I know in StructureMap, we can call something like ObjectFactory.GetInstance()?
What is the equivalent in Ninject?
Thanks
I assume you have looked at the official WCF extension? I usually define my own service factory (referenced in the .SVC file) and reference my Ninject module from there.
As for getting an instance from an interface (i.e. the opposite of having it injected), you do so via the kernel. (You can always have an instance of IKernel injected into any of your classes by adding it to your constructor.) Once you have it, you just use:
kernel.Get<IYourInterface>();
I'm running a WCF service hosted in a Windows service; dependencies of the WCF service are injected via Unity, which is all good. As a result, the service is also easy to write unit tests for.
Recently, I added functionality to the service that makes use of the OperationContext to inspect incoming messages. Unfortunately this rather blows the testability of the service out of the water, owing to Microsoft's fondness for sealed and/or static classes and lack of interfaces and/or virtual methods.
So I turned to the .NET'ers favourite tool in this situation, a wrapper class. Since this is a common problem, someone's already done the hard work for us. So this adds a new dependency to my WCF service, an implementation of IOperationContext. This was no problem for my unit tests, NSubstitute is my mock framework of choice (like Moq, but without the curse of the .Object).
However, when I try to fire up the service for real, I have the following problem - the OperationContext which is being wrapped has not been initialised at the time the IoC container registrations are done. My initialisation code (using Unity here) is:
container.RegisterType<IOperationContext, OperationContextWrapper>(new InjectionConstructor(OperationContext.Current));
but at this point, OperationContext.Current is null, so Unity promptly throws an exception, and my dreams of retiring before 40 go up in smoke.
So, the question is: how do you get WCF to play nicely with DI and a wrapped OperationContext?
Maybe I'm not understanding, but I'm not sure why you want to inject OperationContext.Current into your wrapper. If OperationContextWrapper is wrapping OperationContext, than why not just have it's implementation interact directly with OperationContext.Current where it needs to? I presume the code you're trying to keep testable is not OperationContextWrapper, but rather the code that depends on it via the IOperationContext interface? Then who care what OperationContextWrapper does?
OperationContext.Current is a settable property. Can you change your test initialization to
OperationContext.Current = new OperationContextWrapper();
and have it work that way? If you need it in unity, you could also:
var oc = new OperationContextWrapper();
OperationContext.Current = oc;
container.RegisterInstance<IOperationContext>(oc);
You can also use Microsoft Fakes :
using (ShimsContext.Create())
{
ShimOperationContext shimOperationContext = new
ShimOperationContext(); shimOperationContext.SessionIdGet = () => "sessionId";
OperationContext.Current = shimOperationContext;
}
Please don't respond with ServiceKnownType, as I don't know what the concrete implementation will be.
The interface is designed to be created from an ioc container. I created a ServiceHostFactory that adds a IInstanceProvider that grabs the service from the container.
What I want know is to be able to add IInstanceProviders to the client side calls for the parameters.
var factory = new WebChannelFactory<ITestService>(new Uri("http://localhost:30646/TestService.svc"));
var service = factory.CreateChannel();
var result = service.TestMethod("sdf");
This is how I am creating proxy on the client side. Imagine I have a return type as ICustomType.
Is there a way I can tell the factory above to use a certain instance provider with trying to create interfaces? That way, I can call my container for the instance.
There is no IInstanceProvider model on the client side - it is for creating the services instances when they are required.
You could derive from ChannelFactory and do your IoC resolution in there
btw: You do know that ServiceKnownType can take a method rather than a type which can return the valid known types at runtime?
I'm creating a service reference to a web service written in Java. The generated classes now follow the Java casing convention used in the web service, for example class names are camelCase rather than PascalCase.
Is there a way to get the desired casing from the service reference?
CLARIFICATION:
With WSE based services, one could modify the generated Reference.cs to provide .NET standard casing and use XmlElementAttribute to map to the Java naming presented by the external web service, like this:
[System.Xml.Serialization.XmlElementAttribute("resultType", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Runtime.Serialization.DataMember]
public virtual MyResultType ResultType
{ ... }
Not terribly maintenance-friendly without writing custom code to either generate the proxy code or modify it after it's been generated.
What I'm after is one or more options to present a WCF generated client proxy to calling applications using the .NET casing conventions, achieving the same as I did previously with WSE. Hopefully with less manual effort.
Well, since your WCF client proxies are partial classes, you could always add a second file for the same class, which implements the PascalCasedMethodName for each javaCasedMethodName and then just call the Java method from your new method.
public partial class MyClientProxy
{
......
public MyResultType GetResultType(string inputParam)
{
return this.getResultType(inputParam);
}
......
}
Seems a bit redundant - but that should really work, I think. Since your code is stored in a separate file, it won't be overwritten if you re-create the client proxy - and since it's the second part of a partial class, it will be "merged into" the class definition for your client code to call.