I have a scenario that i have a Client of webAPi that need base url in it's constructor and An configuration manager class that reads configuration from web.config.
interface IConfigManager
{
string baseurl {get;}
}
class ConfigManager:IConfigManager
{
public string baseurl => system.configuration.ConfigruationManager.AppSettings["URL"];
}
and i have a client class that calls the web api
interface IApiClient
{
List<Products> GetProducts(string addresssufix);
}
public class ApiClient:IApiClient
{
public ApiClient(string baseUrl)
{
//----
}
List<Products> GetProducts(string addresssufix)
{
//....
}
}
so i require Url in APiClient
in simple injector while registration of components.
container.Register<IConfigManager, ConfigManager>();
var config= container.GetInstance<IConfigManager>();
container.Register<IApiClient<(()=> new ApiClient(config.baseurl));
but it said i can't register after calling GetInstance
Simple Injector blocks any calls to Register after the first call to GetInstance to force strict registration between registration and resolve. This design prevents strange, hard to debug, and hard to verify behaviour as explained in more detail here in the documentation.
But just as you want to separate the registration phase from the phase where you start resolving from the container, you should do the same when reading configuration values. Configuration values should only be loaded at application start-up, before or during the time of the registration phase. Delaying the reading of configuration values causes applications to become brittle and forces you to go through the complete application to find out whether or not the application is configured correctly, while this can easily be prevented by loading the configuration at start-up (and thus letting the application fail fast).
This means, that in your situation it doesn't make much sense to have an IConfigManager abstraction, since it's only goal is to delay the loading of base URL from the app settings, while again, this should be done directly at start-up (and should preferably fail in case that value is missing or malformed).
With that in mind, I would like to propose the following improvement and simplification to your design:
var container = new Container();
string baseUrl = System.Configuration.ConfigruationManager.AppSettings["URL"];
if (string.IsNullOrEmpty(baseUrl))
throw new ConfigurationErrorsException("appSettings/URL is missing.");
container.RegisterSingleton<IApiClient>(new ApiClient(baseUrl));
See how the configuration is read directly at startup and checked immediately whether the value exists. After that the baseUrl is used directly in the ApiClient constructor. Also note that ApiClient is registered as Singleton. I assume here that ApiClient is stateless and immutable (which is a good practice).
Note that you did the right thing by letting your ApiClient depend on the string baseUrl configuration value, instead of injecting the IConfigManager. Using ConfigManager as an abstraction in application code is typically problematic. Such configuration abstraction will typically grow indefinitely during the lifetime of the application, since every time a new configuration value is added to the configuration, this abstraction (and its implementation and possible fake implementations) need to be updated. Consumers of that abstraction will typically only depend on one or a few configuration values, but never on all. This is an indication of a Interface Segregation Principle violation. Problem with that is that it becomes harder to test consumers of that interface, because you typically want to be sure that they use the correct configuration values. Another problem is that from the definition of such a consumer (its type name and its constructor with required dependencies) it becomes impossible to see which configuration values are actually required.
All these problems go away completely when you let consumers depend directly on the configuration value they require. But again, this even removes the need to have this IConfigManager abstraction in the first place.
Do note that although register-resolve-register is not permitted, you would be able to do the following instead:
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient>(() =>
new ApiClient(container.GetInstance<IConfigManager>().baseurl));
What is going on here is that GetInstance<IConfigManager> is called as part of the delegate for IApiClient. This will work because in that case the GetInstance<IConfigManager>() is called while resolving the IApiClient and thus after the registration process. In other words, resolving IConfigManager is delayed.
Big warning about this though: This practice is typically not advised. As explained before, when it comes to configuration values, we don't want to load them lazily. But even in other cases, we typically don't want to do this, because this construct blinds Simple Injector's verification and diagnostic system. Since Simple Injector uses statically available information (such as constructor arguments) to analyse your object graphs, such dynamic call will disallow Simple Injector to find common problems such as Lifestyle Mismatches. In other words, this construct should only be used in rare cases were you're sure that misconfigurations won't occur.
Pass the dependent object to ApiClient, instead of just a property of it. If that object has too many properties in which ApiClient is not interested, do interface segregation.
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient, ApiClient>();
public ApiClient(IConfigManager configManager)
{
this.baseurl = configManager.baseurl;
}
container.GetInstance<ApiClient>();
Related
In ASP.NET Core 2 Web Api, I want to use dependency injection to inject httpClientA instance of HttpClient to ControllerA, and an instance httpClientB of the HttpClient to ControllerB.
The DI registration code would look something like:
HttpClient httpClientA = new HttpClient();
httpClientA.BaseAddress = endPointA;
services.AddSingleton<HttpClient>(httpClientA);
HttpClient httpClientB = new HttpClient();
httpClientB.BaseAddress = endPointB;
services.AddSingleton<HttpClient>(httpClientB);
I know I could subclass HttpClient to make a unique type for each controller, but that doesn't scale very well.
What is a better way?
UPDATE
Specifically regarding HttpClient Microsoft seems to have something in the works
https://github.com/aspnet/HttpClientFactory/blob/dev/samples/HttpClientFactorySample/Program.cs#L32 - thanks to #mountain-traveller (Dylan) for pointing this out.
Note: This answer uses HttpClient and a HttpClientFactory as an example but easily applies to any other kind of thing. For HttpClient in particular, using the new IHttpClientFactory from Microsoft.Extensions.Http is preferred.
The built-in dependency injection container does not support named dependency registrations, and there are no plans to add this at the moment.
One reason for this is that with dependency injection, there is no type-safe way to specify which kind of named instance you would want. You could surely use something like parameter attributes for constructors (or attributes on properties for property injection) but that would be a different kind of complexity that likely wouldn’t be worth it; and it certainly wouldn’t be backed by the type system, which is an important part of how dependency injection works.
In general, named dependencies are a sign that you are not designing your dependencies properly. If you have two different dependencies of the same type, then this should mean that they may be interchangeably used. If that’s not the case and one of them is valid where the other is not, then that’s a sign that you may be violating the Liskov substitution principle.
Furthermore, if you look at those dependency injection containers that do support named dependencies, you will notice that the only way to retrieve those dependencies is not using dependency injection but the service locator pattern instead which is the exact opposite of inversion of control that DI facilitates.
Simple Injector, one of the larger dependency injection containers, explains their absence of named dependencies like this:
Resolving instances by a key is a feature that is deliberately left out of Simple Injector, because it invariably leads to a design where the application tends to have numerous dependencies on the DI container itself. To resolve a keyed instance you will likely need to call directly into the Container instance and this leads to the Service Locator anti-pattern.
This doesn’t mean that resolving instances by a key is never useful. Resolving instances by a key is normally a job for a specific factory rather than the Container. This approach makes the design much cleaner, saves you from having to take numerous dependencies on the DI library and enables many scenarios that the DI container authors simply didn’t consider.
With all that being said, sometimes you really want something like this and having a numerous number of subtypes and separate registrations is simply not feasible. In that case, there are proper ways to approach this though.
There is one particular situation I can think of where ASP.NET Core has something similar to this in its framework code: Named configuration options for the authentication framework. Let me attempt to explain the concept quickly (bear with me):
The authentication stack in ASP.NET Core supports registering multiple authentication providers of the same type, for example you might end up having multiple OpenID Connect providers that your application may use. But although they all share the same technical implementation of the protocol, there needs to be a way for them to work independently and to configure the instances individually.
This is solved by giving each “authentication scheme” a unique name. When you add a scheme, you basically register a new name and tell the registration which handler type it should use. In addition, you configure each scheme using IConfigureNamedOptions<T> which, when you implement it, basically gets passed an unconfigured options object that then gets configured—if the name matches. So for each authentication type T, there will eventually be multiple registrations for IConfigureNamedOptions<T> that may configure an individual options object for a scheme.
At some point, an authentication handler for a specific scheme runs and needs the actual configured options object. For this, it depends on IOptionsFactory<T> whose default implementation gives you the ability to create a concrete options object that then gets configured by all those IConfigureNamedOptions<T> handlers.
And that exact logic of the options factory is what you can utilize to achieve a kind of “named dependency”. Translated into your particular example, that could for example look like this:
// container type to hold the client and give it a name
public class NamedHttpClient
{
public string Name { get; private set; }
public HttpClient Client { get; private set; }
public NamedHttpClient (string name, HttpClient client)
{
Name = name;
Client = client;
}
}
// factory to retrieve the named clients
public class HttpClientFactory
{
private readonly IDictionary<string, HttpClient> _clients;
public HttpClientFactory(IEnumerable<NamedHttpClient> clients)
{
_clients = clients.ToDictionary(n => n.Name, n => n.Client);
}
public HttpClient GetClient(string name)
{
if (_clients.TryGet(name, out var client))
return client;
// handle error
throw new ArgumentException(nameof(name));
}
}
// register those named clients
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("A", httpClientA));
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("B", httpClientB));
You would then inject the HttpClientFactory somewhere and use its GetClient method to retrieve a named client.
Obviously, if you think about this implementation and about what I wrote earlier, then this will look very similar to a service locator pattern. And in a way, it really is one in this case, albeit built on top of the existing dependency injection container. Does this make it better? Probably not, but it’s a way to implement your requirement with the existing container, so that’s what counts. For full defense btw., in the authentication options case above, the options factory is a real factory, so it constructs actual objects and doesn’t use existing pre-registered instances, so it’s technically not a service location pattern there.
Obviously, the other alternative is to completely ignore what I wrote above and use a different dependency injection container with ASP.NET Core. For example, Autofac supports named dependencies and it can easily replace the default container for ASP.NET Core.
Another option is to
use an additional generic type parameter on the interface or a new interface implementing the non generic interface,
implement an adapter/interceptor class to add the marker type and then
use the generic type as “name”
I’ve written an article with more details: Dependency Injection in .NET: A way to work around missing named registrations
Use named registrations
This is exactly what named registrations are for.
Register like this:
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientA");
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientB");
And retrieve this way:
var clientA = container.Resolve<HttpClient>("ClientA");
var clientB = container.Resolve<HttpClient>("ClientB");
If you want ClientA or ClientB automatically injected into another registered type, see this question. Example:
container.RegisterType<ControllerA, ControllerA>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientA") // Resolve parameter of type HttpClient using name "ClientA"
)
);
container.RegisterType<ControllerB, ControllerB>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientB") // Resolve parameter of type HttpClient using name "ClientB"
)
);
Use a factory
If your IoC container lacks any ability to handle named registrations, you could inject a factory and let the controller decide how to get the instance. Here is a really simple example:
class HttpClientFactory : IHttpClientFactory
{
private readonly Dictionary<string, HttpClient> _clients;
public void Register(string name, HttpClient client)
{
_clients[name] = client;
}
public HttpClient Resolve(string name)
{
return _clients[name];
}
}
And in your controllers:
class ControllerA
{
private readonly HttpClient _httpClient;
public ControllerA(IHttpClientFactory factory)
{
_httpClient = factory.Resolve("ClientA");
}
}
And in your composition root:
var factory = new HttpClientFactory();
factory.Register("ClientA", new HttpClient());
factory.Register("ClientB", new HttpClient());
container.AddSingleton<IHttpClientFactory>(factory);
Really the consumer of the service should not care where about the implementation of the instance it is using. In your case I see no reason to manually register many different instances of HttpClient. You could register the type once and any consuming instance that needs an instance will get it's own instance of HttpClient. You can do that with AddTransient.
The AddTransient method is used to map abstract types to concrete services that are instantiated separately for every object that requires it
services.AddTransient<HttpClient, HttpClient>();
Imagine some SOA. We have a few different services, of which the OperationContext is extended by some SecureOperationContext which makes sure certain security demands are met.
Assume furthermore that sometimes we might need to know a certain property from this SecureOperationContext somewhere else, in a place where there is and won't be this SecureOperationContext. For example a username for some sort of logging purpose.
Currently we're using something that looks and smells plain dirty. The fat's dripping of in my opionion.
Now, in some 'Common' library, there is a class defined with a ThreadStatic property: Username. I guess you can catch my drift: the security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This thing bugs me, but on the other hand what else to do? I was thinking about creating a method that takes a string as parameter to handle this, but then all my methods need to still read that username property, which is non-dry.
So on one hand, this way everything is handled on the background, but I'm not just quite happy having to maintain some (global) class just to achieve this.
Any tips?
I'm not sure how to put it in less abstract terms, but here goes (in pseudo).
public WebService
{
public Save(Car car)
{
// Some SecurityCOntext is known here, this holds top secret info,
// like the username
// and sets this into the golbal helper class UserNameManagemer
// car has for example a CreatedDate property (from an Interface),
//but I don't want handle do this propertyin every Create method can handled in some general piecei of code.
efcontainer.AddObjcect(car)
e.SaveChanges() ->
//Now savechanges will check the objects in the ObjectSatateManager
//and sets the apppriopriate property via the global thing.
}
}
Now what to do to rid myself of this global variable!. Passing a username to SaveChanges is undesirable ass well, since we'd then still have to manually repat this for everything, which blows.
Encapsulate the global property in a service. Define an interface for that service. Now, depend on that interface everywhere you need the data by having a constructor parameter of that type.
This is called dependency injection and is a very important concept when you want to avoid problems as the one you currently have. A dependency injection container such as Autofac can help if you have a big application, but is not strictly required.
The most important thing is to understand dependency injection and have a well-defined composition root, no matter whether you use a DI container or do it yourself.
The security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This sounds like the data is determined dynamically. Note that you can still use a service to track the value. That service also knows whether the value is available or not. This way, you can better manage the temporal coupling that you have at the moment.
Edit: You can further improve the design by creating the client objects through a factory. That factory can ensure that the value is available, so it couples the lifetime of the client objects to the availability of the value. This way, you are sure to always act in a context where the value can be safely accessed.
I'm using Simple Injector with an ASP.NET Web API project, and I want to use different implementations for one interface, depending on the version of REST endpoint used. For example, if v1 of an endpoint is used, IPaymentData should be instantiated with a class called PaymentData, but if v2 is used IPaymentData should be implemented by a class called PaymentDataNew. This is turning out to be problematic!
I don't want to use a composite class like a part of Simple Injector documentation suggests since that means that my code needs to be aware of and take into account the injection framework I'm using (bad).
I noticed in the latest version (3.0) that something called "Context based injection" is a feature. Using the container.RegisterConditional function it should be possible to run a delegate each time a type is resolved.
container.RegisterConditional(typeof(IPaymentData),
c => ((HttpContext.Current.Items["version"] as string ?? "1") == "2")
? typeof(PaymentDataNew)
: typeof(PaymentData),
Lifestyle.Scoped,
c => true);
This doesn't seem to work, though, since even though the lifetime is scoped, and the default lifestyle is WebApiRequestLifestyle the delegate which returns the implementation depending on version is only called for the first request that comes in. Subsequent requests skip this (they seem to be using a cached implementation).
Is there something I'm missing? How can I make sure the delegate is called each time a request comes in??
since that means that my code needs to be aware of and take into account the injection framework I'm using
Not exactly. The composite pattern is a well known and commonly used pattern, so defining it in your code doesn't make your code dependent on the DI library. And if you don't want to define the composite in your application code, you can always specify it inside your Composition Root. The Composition Root already has a very strong dependency on the DI library, so any library-specific stuff should be placed there.
Using the container.RegisterConditional function it should be possible to run a delegate each time a type is resolved.
Simple Injector v3's RegisterConditional method allows applying registrations conditionally based on static information. This means that the supplied predicate is only called a finite amount of time (usually once per consuming component). The methods (IntelliSense/XML) documentation states:
The predicate will only be evaluated a finite number of times; the predicate is unsuited for making decisions based on runtime conditions.
It will not be called every time you resolve it. The reason for this is two-fold:
This optimizes performance, because the decision made in the predicate can be burned into the compiled expression, but more importantly,
This prevents you from making runtime decisions during the building of the object graph.
The shape of your object graph should not be dependent on runtime parameters (such as the version in your HttpContext). Doing this complicates the object graph and makes it very hard to verify and diagnose the object graph for correctness.
The solution I would advice is to implement a proxy implementation for IPaymentData that allows making the switch at runtime. This is not a Simple Injector specific implementation; you should strive to have simple, static, and verifiable object graphs, independently of the DI library you use.
This is how such proxy might look like:
public sealed class HttpRequestVersionSelectorPaymentData : IPaymentData
{
private readonly PaymentData paymentOld;
private readonly PaymentDataNew paymentNew;
public VersionSelectorPaymentData(PaymentData old, PaymentDataNew paymentNew) { ... }
private bool New => HttpContext.Current.Items["version"] as string ?? "1") == "2";
private IPaymentData PaymentData => this.New ? paymentNew : paymentOld;
// IPaymentData method(s)
public Payment GetData(int id) => this.PaymentData.GetData(id);
}
Although it is absolutely possible to make runtime decisions during the building of the object graph (by registering a delegate), I strongly advice against doing this, for the reasons expressed above.
I am attempting to use Ninject on my current project, and up to now, have been loving it. I am in the middle of attempting to configure an IInterceptor object to intercept and handle a failed method call to my service layer. This is hosted in an ASP.NET MVC 5 application.
In the IInterceptor, I've tried several things, such as:
Setting private variables using constructor injection, but came to discover that it appears Ninject will reuse an IInterceptor instance for a method indefinitely, and I haven't found a way to stop that. Since one of the things I bring into scope is a DbContext which gets disposed elsewhere, it ends up failing on any future requests than the one it was created on.
I found that the IInvocation has a Request.Kernel property. However, when I attempt to resolve my UOW from the container, which is .InRequestScope(), it fails, since it attempts to resolve the IUowService dependencies, (one of the dependencies depends on the HttpContext which is null at this point), but appears to be doing so outside the Request scope. It is ignoring the fact that the dependencies it needs have already been created within the ASP.NET request, and is attempting to create new ones.
Setting a binding for the interceptor this.Bind<NinjectExceptionHandler>().ToSelf().InTransientScope(), yet this didn't seem to stop the caching of the interceptor.
I imagine there is something I am missing. I understand wanting to cache IInterceptor objects for performance, but I find it irksome that I can't easily use the IOC container or Injection to get the objects I need for my request.
This is the last issue I am having with getting interception up and running as I need, so any help is greatly appreciated!
Per your request i'm going into more detail on how we've achieved "1 proxy : 1 interceptor" instance relation ship.
We've taken the easy way which does not offer as much flexibility as what the official ninject interception extensions offers. We are relying directly on castle.core dynamic proxy and thus castle's IInvocation interface.
(Please not the code below is for a proxy without target, but a proxy with target is quite similar -- the only thing which changes is that you'll need to know the target class type and use IResolutionRoot.Get<TargetClassType>() to instanciate it).
Basically we created a binding like:
IBindingRoot.Bind<IFoo>()
.ToProvider<InterfaceProxyWithoutTargetProvider<IFoo>>();
Now of course we need to know which interceptors the proxy shall use. Again we are using an easy - and not so nice - design:
public interface IInterceptorBindingDefinition<TTarget>
{
Type InterceptorType { get; }
}
public class InterceptorBindingDefinition<TTarget, TInterceptor> : IInterceptorBindingDefinition<TTarget>
where TInterceptor : IInterceptor
{
Type InterceptorType { get { return typeof(TInterceptor); } }
}
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, LoggingInterceptor>();
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, SomeOtherInterceptor>();
This means IFoo shall get two interceptors: LoggingInterceptor and SomeOtherInterceptor.
and the implementation of the provider:
public class InterfaceProxyWithoutTargetProvider<TInterface> : IProvider<TInterface>
where TInterface : class
{
private readonly IProxyGenerator proxyGenerator;
private readonly IInterceptorFactory interceptorFactory;
public InterfaceProxyWithoutTargetProvider(IProxyGenerator proxyGenerator, IInterceptorFactory interceptorFactory)
{
this.proxyGenerator = proxyGenerator;
this.interceptorFactory = interceptorFactory;
}
public Type Type
{
get { return typeof(TInterface); }
}
public object Create(IContext context)
{
var interceptorTypes = context.Kernel.Get<IEnumerable<IInterceptorBindingDefinition<TInterface>>();
IList<IInterceptor> interceptors = interceptorTypes
.Select(x => x.InterceptorType)
.Select(x => context.ContextPreservingGet(x))
.ToList();
return this.proxyGenerator.CreateInterfaceProxyWithoutTarget<TInterface>(interceptors);
}
}
Now of course we polished the thing a little bit so we have a fluent syntax configuring the binding of the proxy and the interceptor - which is easy enough.
However ninject.extensions.interception's approach with its IAdviceRegistry and IAdvice is certainly better (but also requires more insight into how ninject works).
So it appears that there is no way to do what I was trying gracefully with Ninject. Once in the IInterceptor and in the later parts of async operations, the HttpContext was lost and Ninject couldn't resolve things that really it should have thought were in scope. Coupled with the fact that it reused IInterceptor's for a method (like I said, understandable, but irritating), I just couldn't get it to work right as I wanted to.
What I was able to do to get around the fact was something simple, yet a little kludgy (I think). Since all the methods that I was intercepting were in my service layer, and all my services implemented a IBaseService through a BaseService abstract base class, which happened to have the objects I needed as properties, I was able to do this in the interceptor:
var uow = (invocation.Request.Target as IBaseService).UnitOfWork;
This allowed me to access my unit of work and Fail it, as well as access the logging instance I was working on.
While this works, I would like to see someway to get interceptor constructor injection working correctly through multiple calls, or calls to the Kernel further down the line to realize that it has already resolved an object still in scope (although I am guessing that it may think its out of scope since ASP.Net abandoned the scope upon await).
For any interested, I am going to try and post about this on my blog soon (see my user page if actually interested, not spamming SO myself).
I am currently weighing up the advantages and disadvantages between DI and SL. However, I have found myself in the following catch 22 which implies that I should just use SL for everything, and only inject an IoC container into each class.
DI Catch 22:
Some dependencies, like Log4Net, simply do not suit DI. I call these meta-dependencies and feel they should be opaque to calling code. My justification being that if a simple class 'D' was originally implemented without logging, and then grows to require logging, then dependent classes 'A', 'B', and 'C' must now somehow obtain this dependency and pass it down from 'A' to 'D' (assuming 'A' composes 'B', 'B' composes 'C', and so on). We have now made significant code changes just because we require logging in one class.
We therefore require an opaque mechanism for obtaining meta-dependencies. Two come to mind: Singleton and SL. The former has known limitations, primarily with regards to rigid scoping capabilities: at best a Singleton will use an Abstract Factory which is stored at application scope (ie. in a static variable). This allows some flexibility, but is not perfect.
A better solution would be to inject an IoC container into such classes, and then use SL from within that class to resolve these meta-dependencies from the container.
Hence catch 22: because the class is now being injected with an IoC container, then why not use it to resolve all other dependencies too?
I would greatly appreciate your thoughts :)
Because the class is now being injected with an IoC container, then why not use it to resolve all other dependencies too?
Using the service locator pattern completely defeats one of the main points of dependency injection. The point of dependency injection is to make dependencies explicit. Once you hide those dependencies by not making them explicit parameters in a constructor, you're no longer doing full-fledged dependency injection.
These are all constructors for a class named Foo (set to the theme of the Johnny Cash song):
Wrong:
public Foo() {
this.bar = new Bar();
}
Wrong:
public Foo() {
this.bar = ServiceLocator.Resolve<Bar>();
}
Wrong:
public Foo(ServiceLocator locator) {
this.bar = locator.Resolve<Bar>();
}
Right:
public Foo(Bar bar) {
this.bar = bar;
}
Only the latter makes the dependency on Bar explicit.
As for logging, there's a right way to do it without it permeating into your domain code (it shouldn't but if it does then you use dependency injection period). Amazingly, IoC containers can help with this issue. Start here.
Service Locator is an anti-pattern, for reasons excellently described at http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. In terms of logging, you could either treat that as a dependency just like any other, and inject an abstraction via constructor or property injection.
The only difference with log4net, is that it requires the type of the caller that uses the service. Using Ninject (or some other container) How can I find out the type that is requesting the service? describes how you can solve this (it uses Ninject, but is applicable to any IoC container).
Alternatively, you could think of logging as a cross cutting concern, which isn't appropriate to mix with your business logic code, in which case you can use interception which is provided by many IoC containers. http://msdn.microsoft.com/en-us/library/ff647107.aspx describes using interception with Unity.
My opinion is that it depends. Sometimes one is better and sometimes another. But I'd say that generaly I prefer DI. There are few reasons for that.
When dependency is injected somehow into component it can be treated as part of its interface. Thus its easier for component's user to supply this dependecies, cause they are visible. In case of injected SL or Static SL that dependencies are hidden and usage of component is a bit harder.
Injected dependecies are better for unit testing cause you can simply mock them. In case of SL you have to setup Locator + mock dependencies again. So it is more work.
Sometimes logging can be implemented using AOP, so that it doesn't mix with business logic.
Otherwise, options are :
use an optional dependency (such as setter property), and for unit test you don't inject any logger. IOC container will takes care of setting it automatically for you if you run in production.
When you have a dependency that almost every object of your app is using ("logger" object being the most commmon example), it's one of the few cases where the singleton anti-pattern becomes a good practice. Some people call these "good singletons" an Ambient Context:
http://aabs.wordpress.com/2007/12/31/the-ambient-context-design-pattern-in-net/
Of course this context has to be configurable, so that you can use stub/mock for unit testing.
Another suggested use of AmbientContext, is to put the current Date/Time provider there , so that you can stub it during unit test, and accelerates time if you want.
This is regarding the 'Service Locator is an Anti-Pattern' by Mark Seeman.
I might be wrong here. But I just thought I should share my thoughts too.
public class OrderProcessor : IOrderProcessor
{
public void Process(Order order)
{
var validator = Locator.Resolve<IOrderValidator>();
if (validator.Validate(order))
{
var shipper = Locator.Resolve<IOrderShipper>();
shipper.Ship(order);
}
}
}
The Process() method for OrderProcessor does not actually follow the 'Inversion of Control' principle. It also breaks the Single Responsibility principle at the method level. Why should a method be concerned with instantiating the
objects(via new or any S.L. class) it needs to accomplish anything.
Instead of having the Process() method create the objects the constructor can actually have the parameters for the respective objects(read dependencies) as shown below. Then HOW can a Service Locator be any different from a IOC
container. AND it will aid in Unit Testing as well.
public class OrderProcessor : IOrderProcessor
{
public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
{
this.validator = validator;
this.shipper = shipper;
}
public void Process(Order order)
{
if (this.validator.Validate(order))
{
shipper.Ship(order);
}
}
}
//Caller
public static void main() //this can be a unit test code too.
{
var validator = Locator.Resolve<IOrderValidator>(); // similar to a IOC container
var shipper = Locator.Resolve<IOrderShipper>();
var orderProcessor = new OrderProcessor(validator, shipper);
orderProcessor.Process(order);
}
I have used the Google Guice DI framework in Java, and discovered that it does much more than make testing easier. For example, I needed a separate log per application (not class), with the further requirement that all my common library code use the logger in the current call context. Injecting the logger made this possible. Admittedly, all the library code needed to be changed: the logger was injected in the constructors. At first, I resisted this approach because of all the coding changes required; eventually I realized that the changes had many benefits:
The code became simpler
The code became much more robust
The dependencies of a class became obvious
If there were many dependencies, it was a clear indication that a class needed refactoring
Static singletons were eliminated
The need for session or context objects disappeared
Multi-threading became much easier, because the DI container could be built to contain just one thread, thus eliminating inadvertent cross-contamination
Needless to say, I am now a big fan of DI, and use it for all but the most trivial applications.
We've landed on a compromise: use DI but bundle top-level dependencies into an object avoiding refactoring hell should those dependencies change.
In the example below, we can add to 'ServiceDependencies' without having to refactor all derived dependencies.
Example:
public ServiceDependencies{
public ILogger Logger{get; private set;}
public ServiceDependencies(ILogger logger){
this.Logger = logger;
}
}
public abstract class BaseService{
public ILogger Logger{get; private set;}
public BaseService(ServiceDependencies dependencies){
this.Logger = dependencies.Logger; //don't expose 'dependencies'
}
}
public class DerivedService(ServiceDependencies dependencies,
ISomeOtherDependencyOnlyUsedByThisService additionalDependency)
: base(dependencies){
//set local dependencies here.
}
I know that people are really saying DI is the only good IOC pattern but I don't get this. I will try to sell SL a bit. I will use the new MVC Core framework to show you what I mean. First DI engines are really complex. What people really mean when they say DI, is use some framework like Unity, Ninject, Autofac... that do all the heavy lifting for you, where SL can be as simple as making a factory class. For a small fast project this is an easy way to do IOC without learning a whole framework for proper DI, they might not be that difficult to learn but still.
Now to the problem that DI can become. I will use a quote from MVC Core docs.
"ASP.NET Core is designed from the ground up to support and leverage dependency injection." Most people say that about DI "99% of your code base should have no knowledge of your IoC container." So why would they need to design from ground up if only 1% of code should be aware of it, didn't old MVC support DI? Well this is the big problem of DI it depends on DI. Making everything work "AS IT SHOULD BE DONE" takes a lot of work. If you look at the new Action Injection is this not depending on DI if you use [FromServices] attribute. Now DI people will say NO you are suppose to go with Factories not this stuff, but as you can see not even people making MVC did it right. The problem of DI is visible in Filters as well look at what you need to do to get DI in a filter
public class SampleActionFilterAttribute : TypeFilterAttribute
{
public SampleActionFilterAttribute():base(typeof(SampleActionFilterImpl))
{
}
private class SampleActionFilterImpl : IActionFilter
{
private readonly ILogger _logger;
public SampleActionFilterImpl(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("Business action starting...");
// perform some business logic work
}
public void OnActionExecuted(ActionExecutedContext context)
{
// perform some business logic work
_logger.LogInformation("Business action completed.");
}
}
}
Where if you used SL you could have done this with var _logger = Locator.Get();. And then we come to the Views. With all there good will regarding DI they had to use SL for the views. the new syntax #inject StatisticsService StatsService is the same as var StatsService = Locator.Get<StatisticsService>();.
The most advertised part of DI is unit testing. But what people and up doing is just testing there mock services with no purpose or having to wire up there DI engine to do real tests. And I know that you can do anything badly but people end up making a SL locator even if they don't know what it is. Where not a lot of people make DI without ever reading on it first.
My biggest problem with DI is that the user of the class must be aware of the inner workings of the class in other to use it.
SL can be used in a good way and has some advantages most of all its simplicity.
I know this question is a little old, I just thought I would give my input.
In reality, 9 times out of 10 you really don't need SL and should rely on DI. However, there are some cases where you should use SL. One area that I find myself using SL (or a variation, thereof) is in game development.
Another advantage of SL (in my opinion) is the ability to pass around internal classes.
Below is an example:
internal sealed class SomeClass : ISomeClass
{
internal SomeClass()
{
// Add the service to the locator
ServiceLocator.Instance.AddService<ISomeClass>(this);
}
// Maybe remove of service within finalizer or dispose method if needed.
internal void SomeMethod()
{
Console.WriteLine("The user of my library doesn't know I'm doing this, let's keep it a secret");
}
}
public sealed class SomeOtherClass
{
private ISomeClass someClass;
public SomeOtherClass()
{
// Get the service and call a method
someClass = ServiceLocator.Instance.GetService<ISomeClass>();
someClass.SomeMethod();
}
}
As you can see, the user of the library has no idea this method was called, because we didn't DI, not that we'd be able to anyways.
If the example only takes log4net as dependency, then you only need to do this:
ILog log = LogManager.GetLogger(typeof(Foo));
There is no point to inject the dependency as log4net provides granular logging by taking the type (or a string) as parameter.
Also, DI is not correlated with SL. IMHO the purpose of ServiceLocator is for resolve optional dependencies.
Eg: If the SL provides an ILog interface, i will write logging daa.
For DI, do you need to have a hard reference to the injected type assembly? I don’t see anyone talking about that. For SL, I can tell my resolver where to load my type dynamically when it needed from a config.json or similar. Also, if your assembly contains several thousand types and their inheritance, do you need thousands cascading call to the service collection provider to register them? That’s where I do see much talk about. Most are talking about the benefit of DI and what it is in general, when it comes to how to implement it in .net, they presented with an extension method for adding reference to a hard linked types assembly. That’s not very decoupling to me.