Attempt to resolve item from Ninject in IInterceptor fails - c#

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).

Related

How to define DbContext scope in WPF application similar to ASP.NET?

I want to use same technology to access my database both from ASP.NET MVC and WPF and decided to use EF Core.
In ASP.NET I can inject DbContext(UnitOfWork, AppBLL etc) into Controller and its lifecycle is scoped to request/response operation. As I understood the scope is created behind the scenes using ASP.NET middleware pipeline.
In WPF however scope must be defined based on the app use case which is completely logical since some times there is need for long operation (for example using DbSet.Local.ToObservableCollection() and DataGrid) and sometimes operation is more trivial (for example update one entity).
I want to achieve somewhat similar behavior to ASP.NET MVC in WPF, basically I want to inject DbContext into ViewModel constructor and then each method to be its own scope thus have different short-lived DbContext each method call.
I use Microsoft.Extensions.DependencyInjection and CommunityToolkit.MVVM for DI and add DbContext using AddDbContext. This makes it scoped but without defining the scopes it is effectively singleton. I do not want to define scope with using(var scope = ...) and GetRequiredService each time I make a db operation since it will pollute my code.
As I said I want it to be sleek like in ASP.NET.
So I tried aspect oriented programming with PostSharp but feels kinda dull to add attributes to each method that uses DbContext also there are concerns about testability.
I tried implementing abstract class which has methods to which lambda with operation is passed and lambda is created inside a using(var scope = ...) expression and thus uses scoped DbContext. At the disposal of the scope DbContext is automatically disposed with it.
These approaches however are still distant from ASP.NET mechanism and
I want DbContext lifecycle to be managed smarter.
If I define DbContext as transient then it is only created on injection into ViewModel and not re-created for methods.
By the way, do I understand correctly that in ASP.NET when DbContext is injected into Controller it is disposed right after the construction, since the scope is finished?
EDIT:
Here is a link to example project Github repository
https://github.com/anguzo/ef-core-in-wpf-example
WpfApp project is example of the problem - you can't update same entity twice since it's already being tracked.
Other WPF projects demonstrate different solutions to this problem I came up with.
The closest to the ASP.NET behavior is using PostSharp custom attribute. It requires attribute to be applied to ViewModel class and modifies each method(excluding "special methods": getters, setters and consturctors).
I am still lost since official Microsoft documentation and other materials on the Internet do not describe proper solution to this problem.
The dependency injection container is an instance class.
With mvc there is a request pipeline that provides the parameters of anything instantiated by it from that container.
The difference between mvc and wpf is that with wpf you don't have that pipeline so you need to provide the container instance somehow whenever you instantiate a class you want anything injected to.
It's covered pretty well here:
https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/ioc
You do not want everything to be a singleton and you do not want to resolve the entire object graph as you crank up your application.
As you spotted, that's impractical anyhow because you want some things to be transient.
Passing the DI container around is a nuisance. You might have any number of layers down to your dbcontext.
What is usual is to make the injection container available throughout the app.
In the code there, they've added a property to App to stash that instance in:
public sealed partial class App : Application
{
public App()
{
Services = ConfigureServices();
this.InitializeComponent();
}
/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public new static App Current => (App)Application.Current;
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
App.Services is your dependency injection container. The magic bag you grab your instances out of.
Where these services are registered they're all singletons there, but your dbcontext should be
services.AddTransient<IMyDbContext, MyDbContext>();
And your repository would take an IMyDbContext in it's constructor which would be supplied out the container.
You need to reference that container exposed by App to resolve an instance:
var repo = App.Current.Services.GetService<IRepository>();
Because it's on App.Current, everywhere in your code will be able to reference it. So long as you have a regular wpf entry point.
Your repository would get an instance of dbcontext via injection and you'd so whatever you're doing with that repository. Once it goes out of scope the repository and dbconnection would be ready for garbage collection so long as they're both Transient.
Transients will be disposed after they go out of scope. Hence if you pass a transient dbcontext down from a mvc controller then it will stay in scope until the response is sent from the controller. It's only going to be torn down after the controller's returned it's result and goes out of scope.
The aspect of the code which I would change is to add an abstracted facade around the di container. You want to be able to moq whatever grabs a class instance out that container if you use it within any classs. If you use app.current in unit testing then you need to instantiate an application object.
What Andy outlines is pretty much what I use, it's commonly referred to as a Service Locator pattern, and has a bit of a reputation as an anti-pattern, but for WPF it is pretty effective if you have some discipline within your team about where and how it is allowed to be used.
I'd recently written a quick snippet on using the ServiceLocator pattern and lazy dependency properties with Autofac which can provide some ideas on how the pattern can be applied:
private readonly IContainerScope _scope;
private ISomeDependency? _someDependency = null;
public ISomeDependecy SomeDependency
{
get => _someDependency ??= _scope.Resolve<ISomeDependency>()
?? throw new ArgumentException("The SomeDependency dependency could not be resolved.");
set => _someDependency = value;
}
public SomeClass(IContainer container)
{
if (container == null) throw new ArgumentNullException(nameof(container));
_scope = container.BeginLifetimeScope();
}
public void Dispose()
{ // TODO: implement proper Dispose pattern.
_scope.Dispose();
}
This gives you a pattern gives you a default lifetime scope for the life of a top-level dependency which could be a MVVM ViewModel, and/or navigation provider, etc. so your dependencies can be managed by Transient, Singleton, or PerLifeTimeScope. (Suited to something like the EF DbContext) So for instance when a form is loaded the DbContext instance can be resolved for the lifetime of that form.
I call the pattern a lazy property pattern as the actual dependency is resolved only if/when it is accessed via the property. The advantage of this is when writing unit tests with classic constructor injection, you need to mock every dependency for every test, where with "lazy" properties you use the Setter for just the dependencies you need. The initialization of the class under test accepts a mocked container that simply throws an exception to fail the test if it's Resolve<T> method is called. (No need to build a functional mock container for tests to resolve mocked dependencies or other such complexity)
The caveat of this pattern, and one suggestion to work with the team on to check is that the _scope reference should only be accessed from the dependency properties, not willy-nilly through the code to resolve dependencies ad-hoc. For instance if a new dependency is needed, declare the property accessor to resolve via the scope rather than just writing a _scope.Resolve<NewDependency>() in the code. While you can still test around such code, you'd need to set up your tests to provide a _scope capable of resolving a Mock, which is honestly messy. Following the property pattern makes testing a lot simpler to provide the expected dependency via the Setter and getting an exception/failure if an unexpected dependency happens to get accessed.
It's not proper-C#-Lazy, though I do use a proper Lazy dependency pattern for injected dependencies, and web projects where the lifetime scope is conveniently managed:
private readonly Lazy<ISomeDependency>? _lazySomeDependency = null;
private ISomeDependency? _someDependency = null;
public ISomeDependency SomeDependency
{
get => _someDependency ??= _lazySomeDependency?.Value
?? throw new ArgumentException("SomeDependency dependency was not provided.");
set => _someDependency = value;
}
public SomeClass(Lazy<ISomeDependency>? someDependency = null)
{
_lazySomeDependency = someDependency;
}
Autofac does support lazy initialization so this pattern means that for normal execution, Autofac provides the properties as Lazy references which will resolve if/when they are accessed. For unit tests, you just initialize with an empty constructor and use the Setters to set the dependencies you expect to actually be used. The above example with 1 dependency doesn't really demonstrate the value of that, but picture a test suite for a class that has 8 or 12 dependencies where a method under test will likely only touch a couple of them.

What is the point of dependency injection container? [duplicate]

This question already has answers here:
What is the difference between an interface and a class, and why I should use an interface when I can implement the methods directly in the class?
(16 answers)
Closed 5 years ago.
With .net core you can register "Services" which as I understand, simply means you can register types to concrete classes.
As such, I decided it's about time I learnt DI and practised it. I understand the concept, and with testing it is massively beneficial. However what confuses me is the idea of registering services and whether it's actually needed.
For example, if I have:
public class MyClass
{
public MyClass(IDataContext)
{
... store it
}
}
Then this means I can inject any class that implements the IDataContext, allowing for fakes and moqs in testing. But why would I register a service and map IDataContext to a concrete class in the startup? Is there something wrong with just using the following in other methods:
DataContext dc = new DataContext(); // concrete
var c = new MyClass(dc);
Edit
This question was around the point of using the container (services) rather than why use an interface in the constructor.
Now those classes where you put this code
public class MyService
{
public void DoSomething()
{
DataContext dc = new DataContext(); // concrete
var c = new MyClass(dc);
c.DoSomething();
}
}
have a hard dependency on DataContext and MyClass. So you can't test MyService in isolation. Classes shouldn't care how other classes do what they do, they should only care that they do what they say they're going to do. That's why we use interfaces. This is separation of concerns. Once you've achieved this, you can unit test any piece of code in isolation without depending on the behavior of outside code.
Registering your dependencies up front in one location is also cleaner and means you can swap dependencies out by changing one location instead of hunting down all the usages and changing them individually.
In my code example at the top, MyService requires the usage of both DataContext and MyClass. Instead, it should be like this:
public class MyService
{
private readonly IMyClass _myClass;
public MyService(IMyClass myClass)
{
_myClass = myClass;
}
public void DoSomething()
{
_myClass.DoSomething();
}
}
public interface IMyClass
{
void DoSomething();
}
public class MyClass : IMyClass
{
private readonly IDataContext _context;
public MyClass(IDataContext context)
{
_context = context;
}
public void DoSomething()
{
_context.SaveSomeData();
}
}
Now MyService isn't dependent on DataContext at all, it doesn't need to worry about it because that's not its job. But it does need something that fulfills IMyClass, but it doesn't care how it's implemented. MyService.DoSomething() can now be unit tested without depending on the behavior of other code.
If you weren't using a container to handle satisfying the dependencies, then you're probably introducing hard dependencies into your classes, which defeats the entire point of coding against an interface in the first place.
Testing in isolation is important. It's not a unit test if you're testing more than one finite piece of code. It's an integration test (which have their own value for different reasons). Unit tests make it quick and easy to verify a finite block of code works as expected. When a unit test isn't passing, you know right where the problem is and don't have to search hard to find it. So if a unit test depends on other types, or even other systems (likely in this case, DataContext is specific to a particular database) then we can't test MyService without touching a database. And that means the database must be in a particular state for testing, which means the test likely isn't idempotent (you can't run it over and over and expect the same results.)
For more information, I suggest you watch Deep Dive into Dependency Injection and Writing Decoupled Quality Code and Testable Software by Miguel Castro. The best point he makes is that if you have to use new to create an instance of an object, you've tightly coupled things. Avoid using new, and Dependency Injection is a pattern that enables you to avoid it. (using new isn't always bad, I'm comfortable with using new for POCO models).
You can inject your dependencies manually. However this can get a very tedious task. If your services get bigger, you will get more dependencies, where each dependency on its own can have multiple dependencies.
If you change your dependencies, you need to adjust all usages. One of the main advantages of a DI container is, that the container will do all dependency resolving. No manual work required. Just register the service and use it wherever you want and how often you want.
For small projects this seems like too much overhead, but if your project grows a little, you will really appreciate this.
For fixed dependencies, which are strongly related and not likely to change, injecting them manually is fine.
Using a DI container has another advantage. The DI container will control the life cycle of its services. A service could be a singleton, transient (each request will get a new instance) or have scoped life time.
For example, if you have a transactional workflow. The scope could match the transaction. While in the transaction, requests to a service will return the same instance.
The next transaction will open a new scope and therefore will get new instances.
This allows you to either discard or commit all instances of one transaction, but prevents that following transaction uses resources from the previous one.
You right, you can create all instances manually. In small projects it's an usual practice. The place in your project where links the classes is called Composition Root, and what you do is Constructor Injection.
IoC-libraries can simplify this code, especially considering complex cases like life-time scopes and group registration.
Inversion of control (of constructing an object)
The idea of this pattern is when you want to construct an object you only need to know about the type of the object and nothing about its dependencies or parameters.
Dependency injection
This pattern is taking the inversion of control pattern a step further by enabling you to directly inject an object into a constructor for example.
Again you only need to know the type of the object you want to get and the dependency container will inject an object.
You also don't need to know if a new object is constucted or if you get a allready existing reference.
The most common used type of dependency injection is constructor injection but you could inject your type into other places like methods.
Seperation of concerns
Generally you register a type by an interface to get rid of the dependency on the type.
This is very helpfull for mocking types when testing and it helps to use the open closed principle.
Martin Fowler on "Inversion of Control Containers and the Dependency Injection pattern".

Can I make ninject instantiate postsharp aspects?

I have an asp.net webapi project and I was to be able to do some aspect orientated programming on the methods within the controllers
[Audit("Getting all foos")]
public IEnumerable<Foo> GetAll()
{
return _fooService.GetAll();
}
The aspect/attribute I've created is called Audit. I'm using ninject for object creation but elsewhere but the aspects just create themselves on their own.
This causes two problems, first I can't inject properties into the aspect so have to manually create objects within the aspect.
Secondly it is breaking my unit tests because I'm not able to override the creation behaviour of the creation of the audit aspect so a real one is created during the tests instead of a mocked one.
I don't have a lot of experience with IOC or ninject so to be honest I'm getting myself a bit mixed up.
Is there a way to force the creation of these aspects via ninject?
I'm using the latest version of all libraries if that helps.
I also came across Ninject Intercept but that seems more like an alternative to postsharp though I could be very wrong about that.
Postsharp modifies your code post compilation. There is no way Ninject can pass dependencies with this approach. But there are some things you can do:
Use Ninject Interception for aspects that need dependencies. This works differently. Ninject will create dynamically a decorator class and calls your aspect before and after the call. That way it can pass the aspect some dependencies.
Aspects are usually used for cross cutting concerns. In these situations it is perfectly reasonable to create an ambient context for the dependencies. This is a static class that provides just one kind of dependency e.g. an IAuditLog.
.
public static class AuditLogProvider
{
public static AuditLog
{
get { return autitLog; }
set {
if (this.auditLog != null) throw new InvlaidOperationExcpetion("Audit is already configured");
this.auditLog = value;
}
}
}
In your bootstrapper you can now initialize that ambient context:
AuditLogProvider.AutitLog = kernel.Get<IAuditLog>();

How to access Ninject.Kernel without using Service Locator pattern

I have read dozens of posts regarding this topic, without finding a clear guideline of how to access the Ninject.Kernel without using the Service Locator pattern.
I currently have the following in the classes that need to use CustomerBusiness (which is my service) and it works fine, but I am well aware that it is not the recommended way of doing it.
private CustomerBusiness _customerBusiness;
private ICustomerRepository CustomerRepository
{
get { return NinjectWebCommon.Kernel.Get<IAccountRepository>(); }
}
private CustomerBusiness CustomerBusiness
{
get
{
if (_customerBusiness == null)
{
_customerBusiness = new CustomerBusiness(AccountRepository);
}
return _customerBusiness;
}
}
public Customer GetCustomer(int id)
{
return CustomerBusiness.GetCustomer(id);
}
This is the Kernel property accessed in the code above:
public static IKernel Kernel
{
get
{
return CreateKernel();
}
}
I've read many suggestions about using a factory for this, but none of them explain how to use this factory. I would really appreciate if anyone could show me the "CustomerFactory" or any other recommended approach including how to use it.
Update
I am using ASP.NET Web Forms and need to access CustomerBusiness from CodeBehind.
Solution
The final solution that I found to be working, was the answer with the most votes found at this post:
How can I implement Ninject or DI on asp.net Web Forms?
It looks like this (Note inheritance from PageBase, which is part of Ninject.Web - that is the key!):
public partial class Edit : PageBase
{
[Inject]
public ICustomerBusiness CustomerBusiness { get; set; }
...
The accepted answer below indirectly lead me to find this solution.
Since you're using NinjectWebCommon, I assume you have a web application of some sort. You really should only access the Ninject kernel in one place - at the composition root. It is the place where you are building the object graph and the only place you should ever need an access to the IoC container. To actually get the dependencies you need, you typically employ constructor injection.
In case of MVC web applications, for example, you have a controller factory using the Ninject kernel and that's the only place which references it.
To expand on your particular situation, your class would accept ICustomerBusiness in its constructor, declaring that it needs an instance of ICustomerBusiness as its dependency:
class CustomerBusinessConsumer : ICustomerBusinessConsumer
{
private readonly ICustomerBusiness customerBusiness;
public CustomerBusinessConsumer(ICustomerBusiness customerBusiness)
{
this.customerBusiness = customerBusiness;
}
...
}
Now, whichever class uses ICustomerBusinessConsumer as its dependency, would follow the same pattern (accepting an instance of ICustomerBusinessConsumer as its constructor parameter). You basically never construct your dependencies manually using new (specific exceptions aside).
Then, you just have to make sure your classes get their dependencies and it's this composition root where you do this. What exactly is composition root depends on the type of an application you are writing (console application, WPF application, web service, MVC web application...)
EDIT: To get myself familiar with the situation in the ASP.NET WebForms realm
I had to look up the details since I've never used it. Unfortunately, WebForms require you to have a parameterless constructor at each of your Page classes, so you can't use constructor injection all the way from the top of the object graph down to the bottom.
However, after consulting Mark Seeman's chapter on composing objects in WebForms, I can rephrase how to deal with this framework's inefficiency, while still acting in line with good DI practices:
Have a class responsible for resolving the dependencies, using the Ninject's kernel you have set up. This may be a very thin wrapper around the kernel. Let's call it DependencyContainer.
Create your container and save it in the application context, so that it's ready when you need it
protected void Application_Start(object sender, EventArgs e)
{
this.Application["container"] = new DependencyContainer();
}
Let's suppose your page class (let's call it HomePage) has a dependency on ICustomerBusinessConsumer. Then DependencyContainer has to allow us to retrieve an instance of ICustomerBusinessConsumer:
public ICustomerBusinessConsumer ResolveCustomerBusinessConsumer()
{
return Kernel.Get<ICustomerBusinessConsumer>();
}
Than in the MainPage class itself, you will resolve its dependencies in the default constructor:
public MainPage()
{
var container = (DependencyContainer) HttpContext.Current.Application["container"];
this.customerBusinessConsumer = container.ResolveCustomerBusinessConsumer();
}
Few notes:
having the dependency container available in the HttpContext must not be tempting to consider it a service locator. In fact, the best practice here (at least from the standpoint of being true to DI) is to have some kind of "implementor" classes to which you will relay the functionality of your page classes.
For example, each action handled by MainPage will be only relayed to its implementor class. This implementor class will be a dependency of MainPage and, as all other dependencies, will be resolved using the container.
The important part is that these implementor classes should be in assemblies not referencing the ASP.NET assemblies and thus without a chance to access the HttpContext
having to write so much code to achieve this is certainly not ideal, but it is only a consequence of the framework's limitation. In ASP.NET MVC applications, for example, this is dealt with in a much better way. There you have single point where you can compose the object graphs and you don't have to resolve them in each top-level class as you have to in WebForms.
the good thing is that while you have to write some plumbing code in the page class constructors, from there down the object graph you can employ constructor injection
Constructor injection is the preferred method for DI with ninject, however it also supports property injection. Take a read of the ninject page around injection patterns here https://github.com/ninject/ninject/wiki/Injection-Patterns.
Both of these are injection patterns unlike service location which is request based, not really injection at all.
The flipside of injection is that you need to control construction. When using MVC all of the wiring to do this is built into the MVC ninject package on nuget

Dependency Injection vs Service Location

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.

Categories

Resources