I am pretty new to C# and I'm having trouble figuring out how to get dependency injection to work when instantiating a new class.
I have an Error class that I use to store basic information about errors, warnings, etc when using Quartz to pass to the UI when something happens with the job. We also want to use the Serilog inside those errors to log in case something happens.
How would I use dependency injection with my Error class to use ILogger (Serilog) when creating a new Error class.
The JobClass that we use has DI with the ILogger. ( I don't know if this matters)
When I do
Error e = new Error();
it wants me to pass the ILogger as parameter.
When I do Error e = new Error(); it wants me to pass the ILogger as parameter.
Well, yeah, you're trying to call a constructor directly, it has to be correct C# code. Dependency injection is at the framework level, not the language level.
With that in mind, if you want to construct an object with DI, you have to ask your framework to construct it for you, with something similar to:
var error = services.GetRequiredService<IError>();
And have your error class implement that interface and register it as a transient dependency (ie, get a new one every call).
I want to stress however that you shouldn't be doing this, DI spreads virally for you. If you want one of these things created for you, simply add an IError parameter to your controller constructor and you'll get sent one on object creation to do whatever you want with it.
Related
I am writing a console app in .Net core. I want to use dependency injection. My architecture is like this. Program contains a TradeProcessor (which does all the work) which in turn makes some CompoundTrades. I have got DI passing some classes into the TradeProcessor via its constructor and that whole ServiceProvider setup. That works fine.
Now, if i want to DI some classes into the CompoundTrade does the TradeProcessor have to pass them in via the constructor? I was under the impression that if you register the class to be constructed, all the classes you want to pass in, then they all got passed in "under the hood". You call CompoundTrade () but the other constructor gets called. Am i confusing that with DI in Asp.Net? What is the best design pattern for doing this? Stick all the ServiceProviders in a static class?
You call CompoundTrade() but the other constructor gets called.
That's not how dependency injection works. If you call a constructor explicitly, you get exactly that constructor.
You will need to reference you container and tell your container to create an instance of that class for you.
If you have an instance that needs to dynamically create new objects that are registered in the container, you will need to pass in the container and then use that to create those new objects. Don't call a constructor directly.
public TradeProcessor(IServiceProvider provider)
{
// save the provider in a field
}
public void ThisNeedsADynamicallyCreatedContainerObject()
{
if(condition)
{
var instance = this.provider.GetService<ICompoundTrade>();
}
else
{
var instance = this.provider.GetService<ISingleTrade>();
}
}
Disclaimer: actual syntax may vary depending on the dependency injection provider you use.
I want to use my child class like this:
throw new MyCustomException()
And I whenever this be invoke I want to wrap it with correlation id which suppose to be injected by the service.
I want to inject it to the base class to avoid writing like that
throw new MyCustomException(correlationID)
but I don't know how to do it in the situation where this should be done with constructor injection.
In other words I want to inject dependency to no parameter constructor. Something like that
class MyBaseException()
{
private IWorkingContext workingContext;
public MyBaseException()
{
this.workingContext = workingContext;
}
}
And yes, I know that normally I need to do it like this:
public MyBaseException(IWorkingContext workingContext)
But want this constructor MyBaseException(IWorkingContext workingContext) to be invoked without parameteres so in the end I could use my child class like MyCustomException() and have the workingContext wrapped in it.
My Windsor registration:
container.Register(Component.For<IWorkingContext>().ImplementedBy<WorkingContext>().LifeStyle.PerWebRequest)
I've tried this approach:
var containerAccessor = HttpContext.Current.ApplicationInstance as IContainerAccessor;
var container = containerAccessor.Container;
var operationContext = container.Resolve<IWorkingContext>();
but it doesn't work (new object is created by Windsor).
The moment you new up an exception - or any class for that matter - it is not managed by your IOC container, so it simply can't help you enrich your exception class.
There are a couple of things you can do, however, some of them of questionable quality:
Use a service locator pattern in the constructor of your exception (very yucky)
Use a factory method/class - registered in your IOC container with a dependency on IWorkingContext - which will actually give you an instance of your exception to throw up the stack. This still means that your exception would have a constructor accepting in a dependency, but the class throwing the exception doesn't know or need to know this. (I would recommend this approach)
A dedicated class, living on the periphery of your domain, designed to catch and subsequently enrich any exceptions bubbling up the stack. This is risky for several reasons:
An incorrect implementation will have you lose the context of the exception (stack trace information mainly)
You are now pretty much enforcing every component to ignore exceptions, as you desperately need that context on the exceptions for logging purposes or what not.
Question the entire approach you're going for. Why not enrich the exceptions at log time with the context, instead of adding this metadata at exception time?
Personally, I'd look at 2 as the most viable option, but it can grow out of control quickly if you have a lot of different custom exceptions throughout your application. I would always look at 4, regardless of which option you go for because sometimes the problem you're trying to solve is the wrong problem.
I'm converting my code to use an IoC Container with StructureMap. Trying to get my head around things, and I feel it's starting to 'click' and I can see how it makes so much sense with the back-end side.
However, I'm working my way down I've spotted a few sitautions where I'm not sure how to make it work. Specifically, the case where my original constructor did something important with an argument that isn't really a dependency, or something that will change at run-time.
Let's say I start with this (pre IoC Container), where I was passing my dependencies using a constructor, but also sending it an ImportantObject that's run-time dependent:
IMyPageViewModel myPageViewModel = new MyPageViewModel(importantObject, dialogManager, pageDisplay, viewModelProvider)
and here it is doing its constructing:
public MyPageViewModel(ImportantObject importantObject, IDialogManager dialogManager,IPageDisplay pageDisplay, IViewModelProvider viewModelProvider)
{
this.dialogManager = dialogManager;
this.pageDisplay = pageDisplay;
this.viewModelProvider = viewModelProvider;
importantObject.DoThatImportantThing();
}
Now, I'm migrating to use the IoC container, and at first I think I should do something like this:
//I need to create an instance to use, so I use my IoC container:
IMyPageViewModel myPageViewModel = container.GetInstance<IMyPageViewModel>();
then letting it resolve it's dependencies, however importantObject is something that's set at runtime. I can't register it as a dependency:
public MyPageViewModel(IDialogManager dialogManager,IPageDisplay pageDisplay, IViewModelProvider viewModelProvider, IContainer container)
{
this.dialogManager = dialogManager;
this.pageDisplay = pageDisplay;
this.viewModelProvider = viewModelProvider;
//however, here I have no access to the important object that I previously passed in my constructor
importantObject.DoThatImportantThing(); //obviously error
}
I thought maybe I should be creating using 'new', and passing the IoC container:
IMyPageViewModel myPageViewModel = new MyPageViewModel(importantObject, container)
then letting it resolve it's dependencies in the constructor:
public MyPageViewModel(ImportantObject importantObject, IContainer container)
{
this.dialogManager = container.GetInstance<IDialogManager>();
this.pageDisplay = container.GetInstance<IPageDisplay>();
this.viewModelProvider = container.GetInstance<IViewModelProvider>();
importantObject.DoThatImportantThing();
}
But that strikes me as not a good idea, specifically, I can't run it with a test register and have it create a dummy/stub "MyPageViewModel" for unit testing.
The only other thing I can think of is to remove all the logic from the constructor and putting it in an initialize method, or property setters. However, this means I have to ensure that initialize is always called before use and it will hide errors/problems.
Are any of these options sensible, how should I manage passing a run-time dependent object in a constructor with Dependency Injection?
I tried to stray away from static factories, as I've read lots about them being anti-pattern/bad practice.
Edit: In response to Bruno Garcia's answer I decided to use a factory type pattern that holds the container and deals with object creation like this:
class PageProvider : IPageProvider
{
public MyPageViewModel GetMyPage(ImportantObject importantObject)
{
//might just get, if it's a single only instance
return MyPageViewModel(ImportantObject importantObject,
container.GetInstance<IDialogManager>(),
container.GetInstance<IPageDisplay>(),
container.GetInstance<IViewModelProvider>())
}
}
StructureMap supports passing arguments to Resolve. This could help you with passing the ImportantObject to the Service you are resolving.
It's worth noting that if you pass your container around, things can get really messy really fast. Avoid using it as a Service Locator.
Ideally you'd use the container to resolve an entry point (e.g: Controller, Consumer worker) and from that point on, there's no direct use of the container anymore. If you need to control the lifetime of the dependencies you are taking into your constructor, there are a number of ways to go about that like:
Taking a Factory or a Func<>.
I suggest you reading carefully the docs of the Container you want to use to understand who controls the lifetime of objects (if a Component implements IDisposable, who's going to dispose it?). When are lifetime scopes created/disposed?
IoC Container's are great but it's very easy to find yourself troubleshooting memory leaks if you don't carefully understand the concept of lifetime ownership.
So I started this new project, and I was trying to incorporate all the new design principles I was reading about, namely trying to make things loosely coupled, testable, and following some patterns.
So I then ran into the issue of having to pass too many factories/managers into my classes constructor, which led me into Dependancy injection.
public class SomeClass
{
public SomeClass(IDBFactory factory, IOrderManager orderManager, ....)
}
So if I use ninject, from what I understand, I would then bind a particular implementation to the class.
So what is going on behind the scenes?
NInject will, whenever I instantiate SomeClass, it will bind the implementation that I defined in the config file?
i.e.
I do:
ISomeClass sc = NInject.Get<ISomeClass>();
and ninject will do:
new SomeClassImpl(pass in all the implementaitons in the constructor)
correct?
I don't know NInject, but most DI Containers support Auto-Wiring, which works this way:
When you request ISomeClass, it looks through its list of all registered types. Using this list, it discovers that the desired implementation of ISomClass is SomeClass.
It will use SomeClass' constructor to create an instance (perhaps using Activator.CreateInstance), so it uses Reflection to figure out which paramters are required.
For each paramameter, it looks at the type and repeats step 1-2 for each.
Thus, the process may be recursive, but in the end, you should end up with a fully populated object graph where all dependencies are satisfied.
I'm still struggling a bit with OOP concepts and dependency injection so bear with me.
I have generated my Linq2Sql model with a User table and now I would like to be able to send a confirmation email to this user so I created a partial class file for my User object and I felt it was natural to add a SendConfirmationEmail() method to the User class. This method will use a MailService to send the actual email and I would like to use dependency injection to pass in the service so I created a constructor overload on the User object like this
public User(IMailService service) : this()
{
_service = service;
}
The SendConfirmationEmail method would look like this
public void SendConfirmationEmail()
{
_service.SendMail(params...);
}
I realize this is a kind of poor mans dependency injection and I hope to switch to a dependency injection framework later as I am getting more grips on this.
The problem for me is that I need to make a reference from my model dll to my service dll which does not seem right and because I am unsure of how nice my linq2sql generated entities plays with Dependency injection frameworks and OOP concepts (I think ninject looks most promising).
I was hoping someone with a bit more experience than me could tell I'm if I am going in the right direction with this. I know I can make it work but I would like to educate my self in doing it in the correct way in the same step.
I personally would change some things in your architecture:
I don't think that SendConfirmationEmail should be a method on your User object. But should be a method on another object with the user as a parameter. (this also better seperates your Dal from the other logic.
Second in this method use something like this:
Services.Get<IMailService>().SendMail(params ...);
You can implement Services as the folowin (just an example):
public class Services
{
protected static Dictionary<Type, object> services = new Dictionary<Type, object>();
private Services()
{
}
static Services()
{
// hard coded implementations...
services.Add(typeof(IMailService), new DefaultMailServiceImplementation());
}
public static T Get<T>() where T : class
{
Type requestedType = typeof(T);
return services[requestedType] as T;
}
}
By using a "Services"-class (or call it what you like) you add an additional layer between the IOC-framework and your code which makes it easy to change IOC-frameworks. Just change the implementation in the Get method to use one. You can also use a hardcoded temporary solution (until you use an IOC-framework) in the static constructor (like I did in the above example).
The problem with that approach is that much of the time the entity is going to come from the LINQ-to-SQL back-end, and so isn't going to use your constructor (LINQ-to-SQL creates objects in its own way; you cannot force LINQ-to-SQL to use your constructor) - so this would only be useful for the (few) objects you create yourself. Data-binding (etc) will also commonly use the parameterless constructor by default.
I wonder if this wouldn't work better as a utility method that accepts the service, or obtains the service itself via a factory / singleton.
I think you're ok doing this, but you might want to do two additional things to protect yourself from future cross-layer dependency problems:
Create an interface for your User
object. You should do this because
not doing so will mean that
everything that consumes this
business object will have to
reference the LINQ dlls
unnecessarily.
Move your dependency injection from
the constructor into a property.
You do this because constructor
injection tends to limit your
ability to dynamically create your
object. Doing this, though poses a
problem, since you would have to
implement a lot of null checking
code for _service. You can fix this
by creating an "empty"
implementation of IMailService and
make it the default value for
_service.