We have a multi-tenant web application in which a many pages operate per-tenant. As a result many of our interfaces look like this
interface ISprocketDeployer
{
void DeploySprocket(int tenantId);
}
It occurred to me that it might be better to simplify these interfaces to be unaware of the tenantId. The pages would also then be unaware of the tenantId, like so
[Inject] // Ninject
public ISprocketDeployer SprocketDeployer { get; set; }
private void _button_OnClick(object sender, EventArgs e)
{
SprocketDeployer.DeploySprocket();
}
The dependency injection framework would then inject the tenant ID as a dependency by looking at the currently authenticated user. Is this a good idea or just an abuse of dependency injection?
It further occurred to me that many implementations also take additional dependencies just for looking up details about the tenant, and that I could reduce the number of dependencies further by just injecting in that detail directly, for example
class SprocketDeployer
{
public SprocketDeployer(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}
void DeploySprocket(int tenantId)
{
var tenantName = _tenantRepository.GetTenant(tenantId).Name;
// Do stuff with tenantName
}
}
Would become
class SprocketDeployer
{
public SprocketDeployer(Tenant tenant)
{
_tenant = tenant;
}
void DeploySprocket()
{
var tenantName = _tenant.Name;
// Do stuff with tenantName
}
}
I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.
At that point I become unsure. While it seemed like a fantastic idea at first I realised that I wasn't sure when to stop adding extra "dependencies". How do I decide what should be a dependency and what should be a parameter?
I would stop short of calling it abuse, but that said:
The general use case of dependency injection (via a container) is to inject pure services that do not directly represent state. One of the immediate problems is informing the container of which instance of your object it should be injecting at run-time. If your SprocketDeployer requires a Tenant, and your system includes many Tenants, how does the container figure out which tenant to supply at runtime?
If you want to avoid passing Tenant around, consider using Thread Local Storage (TLS). However, there will still be some point in the pipeline where the Tenant needs to be added to TLS.
Edit
From your comment:
I solve the problem of figuring out which tenant to supply at runtime
in Ninject by binding the type to a method which examines
HttpContext.Current and using InRequestScope. It works fine, but I've
not seen anything to indicate that this is (or isn't) a recommended
practice.
If I understand you correctly, that sounds like a factory of sorts? If that's the case, I see nothing wrong with it.
A minor nitpick might be: it's nice to be able to not have to be concerned about how your services are scoped. When they are truly stateless services, you can view them as pure swappable components that have no side effects based on container configuration.
As with Phil, I would not call this dependency injection abuse, though it does feel a bit odd.
You have at least a few options. I'll detail a couple that seem the best from the detail you've provided, though these may have been what you were referring to when you said 'I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.'
Option 1: Abstract tenant identification to a factory
It may make perfect sense to have an abstraction that represents the current tenant. This abstraction is a factory, but I prefer the term "provider" because factory connotes creation whereas a provider may simply retrieve an existing object (Note: I realize Microsoft introduced a provider pattern but that's not what I'm referring to). In this context you're not injecting data, instead you're injecting a service. I'd probably call it ICurrentTenantProvider. The implementation is frequently context specific. Right now, for example, it would come from your HttpContext object. But, you could decide a specific customer needed their own server and then inject an ICurrentTenantProvider that would retrieve it from your web.config file.
Option 2: Hide multitenancy entirely
Unless you ever have to do different things based on the tenant[1], it may be better to hide the multitenancy entirely. In this case you'd inject classes, that I'm going to call providers, that are context aware and the result of whose function calls would be based on the current tenant. For example, you might have an ICssProvider and an IImageProvider. These providers alone would be aware that the application supported multitenancy. They may use another abstraction such as the ICurrentTenantProvider referenced above or may use the HttpContxt directly. Regardless of the implementation, they would return context specific to the tenant.
In both cases, I'd recommend injecting a service instead of data. The service provides an abstraction layer and allows you to inject an implementation that's appropriately context aware.
Making the Decision
How do I decide what should be a dependency and what should be a parameter?
I generally only ever inject services and avoid injecting things like value objects. To decide you might ask yourself some questions:
Would it make sense to register this object type (e.g., int tenantId) in the IoC container?
Is this object/type consistent for the standard lifetime of the application (e.g., instance per http request), or does it change?
Will most objects end up dependent on this particular object/type?
Would this object need to be passed around a lot if made a parameter?
For (1), it doesn't make sense to inject value objects. For (2), if it is consistent, as the tenant would be, it may be better to inject a service that's aware of the tenant. If yes to (3), it may indicate a missing abstraction. If yes to (4) you may again be missing an abstraction.
In the vein of (3) and (4) and depending on the details of the application, I could see ICurrentTenantProvider being injected in a lot of places, which may indicate it's a little low level. At that point the ICssProvider or similar abstractions may be useful.
[1] - If you inject data, like an int, you're forced to query and you may end up in a situation where you'd want to replace conditional with polymorphism.
10/14/15 UPDATE BEGIN
A little over three months later I've had a bit of a change of heart on the specific situation I mentioned running into with this approach.
I had mentioned that for a long time now I've also regularly injected the current "identity" (tenantAccount, user, etc.) wherever it was necessary. But, that I had ran into a situation where I needed the ability to temporarily change that identity for just a portion of the code to be executed (within the same execution thread).
Initially, a clean solution to this situation wasn't obvious to me.
I'm glad to say that in the end I did eventually come up with a viable solution - and it has been happily churning away for some time now.
It will take some time to put together an actual code sample (it's currently implemented in a proprietary system) but in the meantime here is at least a high level conceptual overview.
Note: Name the interfaces, classes, methods, etc. whatever you like - even combine things if that makes sense for you. It's just the overall concepts that are important.
First, we define an IIdentityService, exposing a GetIdenity(). This becomes the de facto dependency for getting the current identity anywhere we need it (repos, services, etc. everything uses this).
The IIdentityService implementation takes a dependency on an IIdentityServiceOrchestrator.
In my system the IIdentityServiceOrchestrator implmentation makes use mutliple IIdentityResolvers (of which only two are actually applicable to this discussion: authenticatedIdentityResolver, and manualIdentityResolver). IIdentityServiceOrchestrator exposes a .Mode property to set the active IIdentityResolver (by default this is set to 'authenticated' in my system).
Now, you could just stop there and inject the IIdentityServiceOrchestrator anywhere you needed to set the identity. But, then you'd be responsible for managing the entire process of setting and rolling back the temporary identity (setting the mode, and also backing up and restoring the identity details if it was already in manual mode, etc.).
So, the next step is to introduce an IIdentityServiceOchestratorTemporaryModeSwitcher. Yes, I know the name is long - Name it what you want. ;) This exposes two methods: SetTemporaryIdentity() and Rollback(). SetTemporaryIdentiy() is overloaded so you can set via mode or manual identity. The implementation takes a dependency on the IIdentityServiceOrchestrator and manages all the details of backing up the current existing identity details, setting the new mode/details, and rolling back the details.
Now, again you could just stop there and inject IIdentityServiceOchestratorTemporaryModeSwitcher anywhere you'd need to set the temporary identity. But, then you'd be forced to .SetTemporaryIdentity() in one place and .Rollback() in another and in practice this can get messy if it's not necessary.
So, now we finally introduce the final pieces of the puzzle: TemporaryIdentityContext and ITemporaryIdentityContextFactory.
TemporaryIdentityContext Implements IDisposable and takes a dependency on both the IIdentityServiceOchestratorTemporaryModeSwitcher and an Identity / Mode set via an overloaded constructor. In the ctor we use the IIdentityServiceOchestratorTemporaryModeSwitcher.SetTemporaryIdentity() to set the temporary identity and on dispose we call into IIdentityServiceOchestratorTemporaryModeSwitcher.Rollback to clean things up.
Now, where we need to set the identity we inject the ITemporaryIdentityContextFactory which exposes a .Create() (again overloaded for identity / mode) and this is how we procure our temporary identity contexts. The returned temporaryIdentityContext object itself isn't really touched it just exists to control the lifetime of the temporary identity.
Example flow:
// Original Identity
Using (_TemporaryIdentityContextFactory.Create(manualIdentity)) {
// Temp Identity Now in place
DoSomeStuff();
}
// Back to original Identity again..
That's pretty much it conceptually; obviously a LOT of the details have been left out.
There's also the matter of IOC lifetime that should be discussed. In its purest form as discussed here, generally each of the componenets (IIdentityService, IIdentityServiceOrchestrator, ITemporaryIdentityContextFactory) could be set to a 'PerRequest' lifetime. However, it could get funky if you happen to be spawing multiple threads from a single request... in which case you'd likely want to go with a 'perthread', etc. lifetime to ensure there was no thread crosstalk on the injections.
Ok, hope that actually helps someone (and didn't come across as completely convoluted, lol). I'll post a code sample that should clear things up further as I have time.
10/14/15 UPDATE END
Just wanted to chime in and say you're not alone in this practice. I've got a couple multi-tenant apps in the wild that inject the tenant information where it's needed in the same manner.
However, I have more recently ran into an issue where doing this has caused me quite a bit of grief.
Just for the sake of example lets say you have the following (very linear) dependency graph:
ISomeService -> IDep2 -> IDep3 -> ISomeRepository -> ITenentInfoProvider
So, ISomeService depends IDep2, which depenends on IDep3... so on and so on until way out in some leaf ITenentInfoProvider is injected.
So, what's the problem? Well, what if in ISomeService you need to act on another tenant than the one you're currently logged in as? How do you get a different set of TenantInfo injected into ISomeRepository?
Well, some IOC containers DO have context-based conditional support (Ninject's "WhenInjectedInto", "WhenAnyAnchestorNamed" bindings for example). So, in simpler cases you could manage something hacky with those.
But what if in ISomeService you need to initiate two operations, each against a different tenant? The above solutions will fail without the introduction of multiple marker interfaces, etc. Changing your code to this extent for the sake of dependency injection just smells bad on multiple levels.
Now, I did come up with a container based solution, but I don't like it.
You can introduce an ITenantInfoResolverStratagy and have an implementation for each "way" of resolving the TenantInfo (AuthenticationBasedTenantInfoResolverStratagy, UserProvidedTenantInfoResolverStratagy, etc.).
Next you introduce a CurrentTenantInfoResolverStratagy (registered with the container as PerRequestLifeTime so it's a singlton for the life of your call, etc.). This can be injected anywhere you need to set the strategy that will be used by downstream clients. So, in our example we inject it into ISomeService, we set the strategy to "UserProvided" (feeding it a TenantId, etc.) and now, down the chain, when ISomeRepository asks ITenentInfoProvider for the TenantInfo, ITenentInfoProvider turns around gets it from an injected CurrentTenantInfoResolverStratagy.
Back in ISomeService, the CurrentTenantInfoResolverStratagy could be changed multiple times as needed.
So, why don't I like this?
To me, this is really just an overly complicated global variable. And in my mind just about all the problems associated globals apply here (unexpected behavior due to it being mutable by anyone at any time, concurrency issues, etc. etc. etc.).
The problem this whole thing sets out to solve (mostly just not having to pass the tenantId / tenantInfo around as a parameter) is probably just not worth the inherent issues that come with it.
So what's a better solution? Well there probably is some elegant thing that I'm just not thinking of (maybe some Chain Of Command implemenation?).
But, really I don't know.
It may not be elegant but passing a TenantId / TenantInfo around as a parameter in any tenant related method calls would definitely avoid this whole debacle.
If anyone else has better ideas please by all means chime in.
Related
Firstly, thank you- I have become a better programmer by being "forced to" by Simple Injector.
Very early in the bootstrap of my program I setup my root container and shortly afterward call container.Verify()
Many of my services take a dependency on (my class) ICurrentUser which has methods to retrieve account secrets and configuration. As would be expected these secret are available only after the user has authenticated, which has not occurred during the bootstrapping and call container.Verify().
example:
private readonly string serviceAccount;
public SomeService(ICurrentUser currentUser) {
serviceAccount = currentUser.GetSecret("SomeServiceAccount");
}
This has caused me to change the above to:
private Lazy<string> serviceAccount;
public SomeService(ICurrentUser currentUser) {
serviceAccount =
new Lazy<string>(() => currentUser.GetSecret("SomeServiceAccount"));
}
and then refer to serviceAccount.Value when it is needed.
This seems a bit awkward and complicates the ctor. Alternatively I could postpone the verify until after the user authenticates but I don't really like that as it postpones what should happen after setting up the ctor.
Is there a way for me to split the verify process into an initial lightweight verification of the service relationships but not execute the constructors until a later step?
Constructors should be free of any logic, other than doing precondition checks and storing incoming dependencies, as explained here by Mark Seemann. This means that you should not make any calls to injected dependencies from inside the constructor, because:
Such invocation might fail, causing the construction of object graphs to become unreliable
During creation of the component, the injected dependency graph graph might, at that point, not yet be fully initialized, which makes the constructor fragile.
Invocation of dependencies can cause constructors to depend on the availability of runtime data (such as your user's secrets), or the availability of external resources (such as a database), making it much harder to verify your container's configuration, which is something you are already experiencing. Component's constructors, however, should not rely on the availability of runtime data, as I explained here.
The solution to this problem simply is to store the incoming ICurrentUser dependency in the SomeService class, and only call its GetSecret method when one of SomeService's methods are invoked.
You might be tempted to make loading of the value lazy, especially to prevent having to load it over and over again, which can happen if GetSecret is called many times throughout the lifetime of SomeService.
You should, however, refrain from implementing caching at that level, because that would complicate SomeService and all other consumers of ICurrentUser. Instead, you should either implement caching inside the ICurrentUser implementation -or- wrap the implementation in a Decorator that adds the caching behavior. Registering decorators in Simple Injector is trivial.
I would like to register a singleton component for multiple services and define which constructor to use, depending on which service was used during the resolve call.
I tried this:
_builder.RegisterType<TComponent>()
.As<IService1>()
.FindConstructorsWith(ConstructorFinder1)
.SingleInstance();
_builder.RegisterType<TComponent>()
.As<IService2>()
.FindConstructorsWith(ConstructorFinder2)
.SingleInstance();
But this leads to two different "singleton" instances, depending on which service was used.
So I tried:
_builder.RegisterType<TComponent>()
.As<IService1>()
.FindConstructorsWith(ConstructorFinder1)
.As<IService2>()
.FindConstructorsWith(ConstructorFinder2)
.SingleInstance();
This solves the singleton issue, but sadly the second FindConstructorsWith call overrides the first call, i.e. for both services ConstructorFinder2 is used.
I had assumed (hoped) that the ConstructorFinders would be stored with respect to the service, but apparently this is not the case.
Is what I'm trying to achieve conceptually wrong, does Autofac not support it or am I simply missing something?
EDIT:
Once again thanks to Travis for his great response. Apparently I left out a few details that made things confusing. Let me add some now.
This question was actually a kind of follow-up to How to determine which constructor Autofac uses when resolving (where Travis also helped me along). So the issue comes up when deserializing and it affects many different objects.
I get the arguments about composition, seperation of concerns and how having several ctors is often considered a code smell, but in the context of deserialization (at least for the app I'm currently developing) it is extremely useful to be able to create instances differently, depending on if they are newly built or deserialized from a project file. Several members that need to be initialized when building a new instance do not have to be initialized when deserializing (because their values would be overridden during deserialization anyway). It would mean extra performance costs and (and, in this case) cause other issues regarding the throw-away-initializations.
After spending days trying to find a solution (with complications also coming from the Newtonsoft Json side) I've decided to discontinue Autofac and implement our own IOC container. For general purposes it cannot (obviously!) compete with Autofac in any way, but since we were really only using a small subset of Autofac's great features, I felt we could try to roll our own. It took me a lot less than the days I've spent on trying to wrap my head around a monolithic black box. Yes, Autofac is open source, but stepping through the code no walk in the park.
First tests are very promising and it feels good to regain full control of such a vital component of the application.
Again, the reason for leaving Autofac was that it is not (feasibly) possible to define how a singleton component is constructed depending on the service it was constructed for. And from a general structure/concept point-of-view I understand that it makes sense to strictly seperate the service and the construction-how-tos. But during deserializing things are different, I believe. And, now that I'm independent of Autofac, I may decide to alter the mechanisms so they fit into the overall concept in a more straight-forward way.
This is sort of a difficult question to answer because it seems you have some underlying goal you're trying to achieve and you have a solution you want to work but perhaps it's the wrong solution and you should ask a [new] question depending on how this response works out for you.
Let me walk this through to see if I can explain why it's hard to answer.
I would like to register a singleton component for multiple services and define which constructor to use, depending on which service was used during the resolve call.
If it's a singleton that means there's one in the whole system, right? It'll be effectively "first in wins." If something resolves it as an IService1 then the constructor associated with that will be called and even if you try resolving it as IService2 later no construction will happen because the singleton was created. The converse is also true - IService2 gets resolved and the constructor path is followed there, then things asking for IService1 will get the singleton and no constructor is called.
That raises a concern:
If you know which thing, for sure, will be resolving first, then why do you need two different constructor selectors?
If you don't know which thing will be resolving first, then are you accounting for the system unpredictability?
I have seen these sorts of questions before and usually what they indicate is one of two things:
You are trying to do some sort of selection or special logic based on context. There's an Autofac FAQ about this that may help. Usually the way around this is to refactor. I'll get back to that in a second.
You are trying to "share registrations" between two different applications. The answer to this is to use Autofac modules and reuse those; but if there are special registrations for each app type, let that happen.
This isn't to say that either of these are what you're asking for, but this is where I've seen such questions. Usually there's some unspoken goal where a solution has been pre-chosen and it's better ask how to solve the goal rather than how to implement a very specific solution. Again, I could be wrong.
On the refactoring note for item 1, above, I can further guess based on the desire for a singleton that there's some sort of resource like a database connection that needs to be shared or is expensive to spin up. Consider splitting the TComponent into three separate classes:
TCommonExpensiveComponent - this is the stuff that is actually expensive to spin up and really does need to be a singleton, but does not differ across IService1 and IService2.
TService1 - implement IService1 with only the required constructor so you don't need a constructor finder. Have it consume TCommonExpensiveComponent.
TService2 - implement IService2 with only the required constructor so you don't need a constructor finder. Have it consume TCommonExpensiveComponent.
The idea being avoid the complexity of registrations, keep the shared/singleton that you want, and still get different constructor usage as needed. You may want to throw in some common base/abstract class, too, that the TService classes can derive from if there's really a lot of common logic.
Is what I'm trying to achieve conceptually wrong, does Autofac not support it or am I simply missing something?
Technically you could do some really crazy stuff in Autofac if you wanted to, like write a custom registration source that waits for someone to query for the IService1 or IService2 registration and then picks a constructor based on that, dynamically serving the registration as needed. But, truly, don't even start down this road.
Instead, it would be good to clarify what the problem is that you're trying to solve and how you plan on working around the challenges listed above if my response here doesn't help. Do that in a brand new question that goes into more detail about your challenge and what you've tried. This not being a forum, having a conversation to try and weed out additional help given the current question really isn't feasible. Plus, taking a second to step back and maybe reframe the question sounds like it might help here.
I've got to the point in my design, where I am seriously considering a singleton.
As we all know, the "common" argument is "Never do it! It's terrible!", as if we'd littered our code with a bunch of goto statements.
ServiceStack is a wonderful framework. Myself and my team are sold on it, and we have a complicated web-service based infrastructure to implement. I have been encouraging an asynchronous design, and where possible - using SendAsync on the service-stack clients.
Given we have all these different systems doing different things, it occurred to me I'd like to have a common logger, (A web service in itself actually, with a fall-back to a local text file if the web service is not available - e.g. some demons are stalking the building). Whilst I am a big fan of Dependency Injection, it doesn't seem clean (at least, to me) to be passing a reference to a "use this logger client" to every single asynchronous request.
Given that ServiceStack's failure signature is a Func<TRESPONSE, Exception> (and I have no fault with this), I am not even sure that if the enclosing method that made the call in the first place would have a valid handle.
However, if we had a singleton logger at this point, it doesn't matter where we are in the world, what thread we are on, and what part of a myriad of anonymous functions we are in.
Is this an accepted valid case, or is it a non-argument - down with singletons?
Logging is one of the areas which makes sense to be a singleton, it should never have any side-effects to your code and you will almost always want the same logger to be used globally. The primary thing you should be concerned with when using Singletons is ThreadSafety, which in the case of most Loggers, they're ThreadSafe by default.
ServiceStack's Logging API allows you to both provide a substitutable Logging implementation by configuring it globally on App_Start with:
LogManager.LogFactory = new Log4NetFactory(configureLog4Net:true);
After this point every class now has access to Log4Net's logger defined in the Factory above:
class Any
{
static ILog log = LogManager.GetLogger(typeof(Any));
}
In all Test projects I prefer everything to be logged to the Console, so I just need to set it once with:
LogManager.LogFactory = new ConsoleLogFactory();
By default ServiceStack.Logging, logs to a benign NullLogger which ignores each log entry.
There's only one problem with classic implementation of a singleton -
it is easily accessible, and provokes direct use, which leads to strong coupling,
god objects, etc.
under classic implementation I mean this:
class Singleton
{
public static readonly Singleton Instance = new Singleton();
private Singleton(){}
public void Foo(){}
public void Bar(){}
}
If you use singleton only in terms of an object lifecycle strategy,
and let IoC framework manage this for you, maintaining loose coupling -
there is nothing wrong with having 'just one' instance of a class
for entire lifetime of application, as long as you make sure it is thread-safe.
If you are placing that common logging behind a static facade that application code calls, ask yourself how you would actually unit test that code. This is a problem that Dependency Injection tries to solve, but you are reintroducing it by letting application logic depend on a static class.
There are two other problems you might be having. To question I have for you is: Are you sure you don't log too much, and are you sure you aren't violating the SOLID principles.
I've written an SO answer a year back that discusses those two questions. I advice you to read it.
As always, I prefer to have a factory. This way I can change the implementation in future and maintain the client contract.
You could say that singleton's implmenentation could also change but factories are just more general. For example, the factory could implement arbitrary lifetime policy and change this policy over time or according to your needs. On the other hand, while this is technically possible to implement different lifetime policies for a singleton, what you get then should probably not be considered a "singleton" but rather a "singleton with specific lifetime policy". And this is probably just as bad as it sounds.
Whenever I am to use a singleton, I first consider a factory and most of the times, the factory just wins over singleton. If you really don't like factories, create a static class - a stateless class with static methods only. Chances are, you just don't need an object, just a set of methods.
I have a project where the Ninject is used as IoC container. My concern is that a lot of classes have such kind of constructors:
[Inject]
public HomeController(
UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) {
_userManager = userManager;
_roleManager = roleManager;
_blahblahManager = blahblahManager;
}
What if I don't want to have all instances of these classes at once?
The way, when all this classes are wrapped by Lazy<T> and passed to constructor is not exactly what I need. The T instances are not created yet, but Lazy<T> instances are already stored in memory.
My colleague is suggesting me to use Factory pattern to have control over all instantiations, but I'm not sure that IoC have such great design bug.
Is there a workaround for this situation or IoC really have such big defect in it's design? Maybe I should use another IoC container?
Any suggestions?
Seems to me that you are doing premature optimization: don't do it.
The constructors of your services should do nothing more than storing the dependencies that it takes in private fields. In that case the creation of such an object is really light weight. Don't forget that object creation in .NET is really fast. In most cases, from a performance perspective, it just doesn't matter whether those dependencies get injected or not. Especially when comparing to the amount of objects the rest of your application (and the frameworks you use) are spitting out. The real costs is when you start using web services, databases or the file system (or I/O in general), because they cause a much bigger delay.
If the creation is really expensive, you should normally hide the creation behind a Virtual Proxy instead of injecting a Lazy<T> in every consumer, since this allows common application code to stay oblivious to the fact that there is a mechanism to delay the creation (both your application code and test code are becoming more complex when you do this).
Chapter 8 of Dependency Injection: Principle, Practices, Patterns contains a more detailed discussion about lazy and Virtual Proxies.
However, a Lazy<T> just consumes 20 bytes of memory (and another 24 bytes for its wrapped Func<T>, assuming a 32bit process), and the creation of a Lazy<T> instance is practically free. So there is no need to worry about this, except when you’re in an environment with really tight memory constraints.
And if memory consumption is a problem, try registering services with a lifetime that is bigger than transient. You could do a per request, per web request, or singleton. I would even say that when you're in an environment where creating new objects is a problem, you should probably only use singleton services (but it's unlikely that you're working on such an environment, since you're building a web app).
Do note that Ninject is one of the slower DI libraries for .NET. If that's troubling you, switch to a faster container. Some containers have performance that is near newing up object graphs by hand.
but by all means, do profile this, many developers switch DI libraries for the wrong reasons.
Do note that the use of Lazy<T> as dependency is a leaky abstraction (a violation of the Dependency Inversion Principle). Please read this answer for more information.
Steven is correct in saying that this looks like premature optimization. The construction of these object is very fast and is usually never the bottleneck.
However using Lazy to express a dependency you don't need right away is a common pattern in Dependency Injection frameworks. Actofac is one such container that has built in support for various wrapping types. I'm sure there is also an extension for Ninject as well, maybe take a look at this one, Ninject Lazy.
You can also inject into an action method with the syntax below. (I'm not sure exactly what version this was introduced).
Constructor is best practice, but I had to do this once deliberately when I had a service that was doing some expensive initialization - accidentally in fact - but it wasn't discovered for a while and it was just easiest to move it to the one method that did need it.
This can make for cleaner code if you only need to access a service from one action method - but bear in mind if you inject it to the method you'll have to pass it around everywhere because it will no longer be on this. Definitely don't go assigning to this.service in an action method - that's horrible.
public IActionResult About([FromServices] IDateTime dateTime)
{
ViewData["Message"] = "Currently on the server the time is " + dateTime.Now;
return View();
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2#action-injection-with-fromservices
Other than testability, what's the big advantage of utilizing D.I. (and I'm not talking about a D.I. framework or IoC) over static classes? Particularly for an application where you know a service won't be swapped out.
In one of our c# application, our team is utilizing Dependency Injection in the web web GUI, the service layer, and the repository layer rather than using static methods. In the past, we'd have POCOs (busines entity objects) that were created, modified, passed around, and saved by static classes.
For example, in the past we might have written:
CreditEntity creditObj = CreditEntityManager.GetCredit(customerId);
Decimal creditScore = CreditEntityManager.CalculateScore(creditObj);
return creditScore;
Now, with D.I., the same code would be:
//not shown, _creditService instantiation/injection in c-tors
CreditEntity creditObj = _creditService.GetCredit(customerId);
Decimal creditScore = _creditService.CalculateScore(creditObj);
return creditScore;
Not much different, but now we have dozens of service classes that have much broader scope, which means we should treat them just as if they were static (i.e. no private member variables unless they are used to define further dependencies). Plus, if any of those methods utilize a resource (database/web service/etc) we find it harder to manage concurrency issues unless we remove the dependency and utilize the old static or using(...) methods.
The question for D.I. might be: is CreditEntityManager in fact the natural place to centralize knowledge about how to find a CreditEntity and where to go to CalculateScore?
I think the theory of D.I. is that a modular application involved in thing X doesn't necessarily know how to hook up with thing Y even though X needs Y.
In your example, you are showing the code flow after the service providers have been located and incorporated in data objects. At that point, sure, with and without D.I. it looks about the same, even potentially exactly the same depending on programming language, style, etc.
The key is how those different services are hooked up together. In D.I., potentially a third party object essentially does configuration management, but after that is done the code should be about the same. The point of D.I. isn't to improve later code but to try and match the modular nature of the problem with the modular nature of the program, in order to avoid having to edit modules and program logic that are logically correct, but are hooking up with the wrong service providers.
It allows you to swap out implementations without cracking open the code. For example, in one of my applications, we created an interface called IDataService that defined methods for querying a data source. For the first few production releases, we used an implementation for Oracle using nHibernate. Later, we wanted to switch to an object database, so we wrote and implementation for db4o, added its assembly to the execution directory and changed a line in the config file. Presto! We were using db4o without having to crack open the code.
This has been discussed exactly 1002 times. Here's one such discussion that I remember (read in order):
http://scruffylookingcatherder.com/archive/2007/08/07/dependency-injection.aspx
http://ayende.com/Blog/archive/2007/08/18/Dependency-Injection-More-than-a-testing-seam.aspx
http://kohari.org/2007/08/15/defending-dependency-injection
http://scruffylookingcatherder.com/archive/2007/08/16/tilting-at-windmills.aspx
http://ayende.com/Blog/archive/2007/08/18/Dependency-Injection-IAmDonQuixote.aspx
http://scruffylookingcatherder.com/archive/2007/08/20/poking-bears.aspx
http://ayende.com/Blog/archive/2007/08/21/Dependency-Injection-Applicability-Benefits-and-Mocking.aspx
About your particular problems, it seems that you're not managing your services lifestyles correctly... for example, if one of your services is stateful (which should be quite rare) it probably has to be transient. I recommend that you create as many SO questions about this as you need to in order to clear all doubts.
There is a Guice video which gives a nice sample case for using D.I. If you are using a lot of 3-rd party services which need to be hooked upto dynamically D.I will be a great help.