Autofac Single Instance with event handlers - c#

I have a cache class that is registered as a single instance with Autofac. Whenever I clear the cache I call the method ExecuteCacheCleared();
The cache class looks like this
public IEnumerable<ICacheCleared> _cacheCleared { get; private set; }
public CacheService(IEnumerable<ICacheCleared> cacheCleared) : ICacheService
{
_cacheCleared = cacheCleared;
}
private void ExecuteCacheCleared()
{
if (_cacheCleared != null)
{
foreach (var cacheCleared in _cacheCleared)
{
cacheCleared.EntityCacheChanged();
}
}
}
I then have several concrete implementations of ICacheCleared that are called when ExecuteCacheCleared is called.
So currently I am registering bits in autofac as follows:
builder.RegisterType<CacheService>().As<ICacheService>().SingleInstance();
builder.RegisterType<CacheCleared>().As<ICacheCleared>().InstancePerRequest();
With the above, I get an error (which I get) because the SingleInstance won't work with the InstancePerRequest but in my CacheCleared concrete class i also inject other dependencies that need to be InstancePerRequest.
Hopefully, you can see what I am trying to achieve (basically trying to notify subscribing classes of changes) but I'm stuck on how to achieve this.

What you are trying to do will not be possible by taking a dependency on IEnumerable<>. That relationship type is intended for supporting multiple implementations of a service, not for resolving all instances.
I don't know of any way to do what you're trying to do OOTB. It's a fairly esoteric and difficult scenario. The best way I can think of is to invert the control: require your ICachedCleared implementations to take a dependency on ICacheService. In turn, give ICacheService a method like AddNotifier(ICacheCleared) which could be called from the constructor (if it's cheap--I highly suggest making it cheap) or on first use (if it's expensive--e.g., returns a Task).
AddNotifier() would add each to a collection which would then be called from ExecuteCacheCleared().
This is going to be pretty complex, because you're going to have to be VERY careful with this code in a multi-threaded environment--which you are surely in, since you're using InstancePerRequest(). Also, you're going to have to figure out a way of removing all those instances when the request has completed (use a collection of WeakReferences? Make ICacheCleared implement IDisposable and call a ICacheService.Remove() when disposed?). And probably many other issues I haven't considered.
The complexity of this is high enough that you may want to take a moment and reconsider the design itself before you head down the rabbit-hole.
Good luck!

It's not entirely clear what the intention of your design is. I'm using autofac and have caches which are instanced per request and others which are single instanced. Generally requests should be short lived, anything cached per request should be a snapshot at the time of the request.
Data we cache per request is generally done to avoid reloading or recalculating of data within the one request. It's dubious that you have a requirement to clear a cache instanced per request, even more dubious that you want to clear these caches across all the current requests, I don't understand how or why you would have a need for such functionality.
Anyhow, I think the answer could be very simple. ICacheService also needs to be InstancePerRequest or ICacheCleared needs to be single instanced.
Alternatively you should break up the design of your caches such that you separate the caches instanced per request from those which are single instanced. i.e. have a ICacheService which has a collection of ICacheCleared and a IRequestCacheService which has a collection of IRequestCacheCleared objects.
You can inject single instanced objects into objects instanced per request but not vice versa. So if you like the IRequestCacheService could also be injected with the ICacheService and call ExecuteCacheCleared on the ICacheService when ExecuteCacheCleared is called on the IRequestCacheService.

Related

How can I remove (set to null) a registered singleton type in DryIoC?

I have a requirement to completely delete an instance that is already resolved by DryIoC container (but not unregister the type). I don't know if this is possible?
If I don't use any IoC container and just declare singletons myself I of course can reset it to null easily whenever I want.
e.g:
var instance = DryIocContainer.Resolve<SomeType>();//a singleton
//All next times calling Resolve<> will return just that singleton instance.
//But if that is cleared, the next time calling Resolve<> should create
//a completely new instance (like as the first time it was called).
The scenario here is after user logging off my app, I want to clear all resolved singletons so that if the user logging back using another account (or even with that same account), the data will be refreshed correctly. Currently without being able to clear those singletons, I have to reset all properties manually myself - which I think should just be the last resort.
I don't know if this is possible?
No, this isn't really possible. Although Dadhi pointed to the WithoutSingletonsAndCache method, this effectively builds up a new container with a new set of instances. Although this allows you to replace your particular singleton, it also means that all other singleton registrations will be cleared and you lose the promise of there being only one instance of a particular type. In other words, in able to do this, the container has broken its promise around singletons. This effectively leads to a Torn Lifestyle. You will have closely analyse whether or not this will be a problem or not.
If I don't use any IoC container and just declare singletons myself I of course can reset it to null easily whenever I want.
This is not true. Even without a container, you can't simply replace a singleton. A simple example is when this singleton to be replaced is a dependency of another singleton. Unless you replace that singleton (and all its singleton consumers up the chain), this original instance is captured within its consumer and will the consumer will keep referencing the original instance, even though you try to replace it. This is a form of the Captive Dependency problem.
The only true way to solve this problem, and solve it locally for this instance only, is to create a Proxy for the abstraction of that Singleton. This proxy can wrap that dependency and you can allow it to be changed later on. This allows you to at any moment in time replace the dependency.
How to implement this, does highly depend on your particular needs, but here's an example:
public interface ISomeType
{
void SomeMethod();
}
public class SomeTypeImpl : ISomeType { ... }
public class SomeTypeProxy : ISomeType
{
public ISomeType Dependency { get; set; }
public SomeTypeProxy(ISomeType dependency) {
this.Dependency = dependency;
}
public void SomeMethod() => this.Dependency.SomeMethod();
}
Without a DI container, you can use this as follows:
var proxy = new SomeTypeProxy(new SomeTypeImpl());
// later on
proxy.Dependency = new OtherTypeImpl();
Another option is to let the Proxy wrap a Func<T> delegate, which allows you to move this logic to the delegate:
ISomeType dependency = new SomeTypeImpl();
var proxy = new SomeTypeProxy(() => dependency);
// later on
dependency = new OtherTypeImpl();
The scenario here is after user logging off my app, I want to clear all resolved singletons so that if the user logging back using another account
In your particular case, you are actually describing clearing the complete application. Your scenario sounds similar to restrarting the application. This is probably something that WithoutSingletonsAndCache works good at, because you wish to reset all singletons.
The same however can be achieved with just creating a new container with all its registrations. Your application will already have some sort of CreateContainer class, and it should be a matter of calling that CreateContainer method again.
Of course this method only works when your dealing with an application at only handles one user, instead of having a web application that runs requests for many users concurrently.
You can do:
container = container.WithoutSingletonsAndCache();
Here is the docs.

Keep track of a .net application variable through different requests

In a .Net application when using C# I have to make an expensive call to get some data to a third party API, and depends on this one sometimes it's slower that I would like.
Thing is, that data will be accurate but I can calculate it with less precision on my own. So I was thinking how would I be able to let's say keep track of the average request time during the last 5 minutes and if it's greater than my threshold change to use my own implementation.
A sketch of the method would be something like this:
public int GetMyData()
{
return isTooSlow() ? _ownImplementation.GetData() : thirdParty.GetData();
}
Even if ideally I would like to be able to wrap the third party in an interface which mine would implement and change it on runtime that would be a nice to have.
But the mainquestion would be how to keep that state in memory. I can only think of using a static class and I have read about ApplicationState but not sure if any of those are the best approaches.
Besides, not for my small project but how would any of those solutions scale out? If I had to think about several instances of my application running I think the only solution would be to use an external storage (redis or alike?) and query it when doing the check.
Sorry if the question is too generic but thought it was an interesting problem to solve and don't know exactly how to best approach it
Thanks
I would put the question of multiple application instances on the back burner. Not that it doesn't matter, but if you're programming against interfaces then at some point you could replace your implementation with something that's cached.
If you want average request times over a duration like five minutes then you'll need a list that ejects expired entries. Here's a stab at that:
internal class TimestampedEntry<T>
{
internal DateTimeOffset Timestamp { get; private set; }
internal T Value { get; private set; }
internal TimestampedEntry(T value)
{
Timestamp = DateTimeOffset.Now;
Value = value;
}
}
public class ExpiringList<T>
{
private readonly List<TimestampedEntry<T>> _list = new List<TimestampedEntry<T>>();
private readonly TimeSpan _expiration;
public ExpiringList(TimeSpan expiration)
{
_expiration = expiration;
}
public void Add(T item)
{
lock (_list)
{
_list.Add(new TimestampedEntry<T>(item));
}
}
public IReadOnlyCollection<T> Read()
{
var cutoff = DateTimeOffset.Now - _expiration;
TimestampedEntry<T>[] result;
lock (_list)
{
result = _list.Where(item => item.Timestamp > cutoff).ToArray();
_list.Clear();
_list.AddRange(result);
}
return new ReadOnlyCollection<T>(result.Select(item => item.Value).ToList());
}
}
That ensures that when you read from the list it only returns items stored within the specified interval and also deletes the rest. You could create an ExpiringList<TimeSpan>, add the elapsed time for each call, and then inspect the average as needed.
Where to store it? I'd put it in a class with a single instance. That could be a singleton or a static class. I prefer using a dependency injection container that returns a single instance (like Windsor's singleton lifestyle.) I don't like creating singletons. I'd rather create a "normal" class and then manage it to keep a single instance. DI containers like Windsor make that easy.
I think an important factor in an implementation like this is to keep the messy switching logic separate - hidden in some sort of factory as opposed to having an if/then with all the logic to check the average response times and call either API all in one big class.
For example, if you have an interface representing the call to get data, like IMyDataProvider, then you could define a factory like
interface IMyDataProviderFactory
{
IMyDataProvider Create();
}
Your classes just depend on that factory interface. An class that implements IMyDataProviderFactory checks your average response times and returns either the implementation of IMyDataProvider that calls the external API or an implementation that uses your calculation.
That way the complexity of that logic stays separate from whatever classes depend on the APIs.
Windsor is good with those abstract factories too. Other DI containers also make them easy, and this sort of functionality is built into ASP.NET Core. You weren't asking about dependency injection, but I recommend looking into it. It makes it easier to manage this sort of complexity and keep it maintainable.
Going back to multiple application instances and distributed caches - you can see how the factory pattern implementation makes this easier to manage. Let's say today this is one instance but tomorrow you want to share this data via a distributed cache. Where do you make that change? Most of the code that depends on this API won't need to change at all because it doesn't "know" about any of those implementation details. You would change the code that stores the timing of each API call and change the implementation of your factory.

How to implement this mixed object Lifetime with Simple Injector

I'd like to know how to register the classes and setup a Simple Injector container to instantiate the classes in the following way. ie go from manual DI to having the below Consumer class have the CompositeService injected and the object graph and lifetimes setup as follows:
To bring some context (if it helps) the Consumer class might be a ViewModel from a WPF application which gets instantiated when the View is requested.
public class Consumer
{
public Consumer()
{
var sharedSvc = new SharedService();
var productSvc = new ProductService(sharedSvc, new MathHelper());
var compositeSvc = new CompositeService(sharedSvc, productSvc, new MathHelper());
compositeSvc.Process();
}
}
where:
MyContext should be shared within the scope of the calls.
ProductService and CompositeService can be transient or shared within the scope.
MathHelper must be transient.
Q: How can the above be achieved with Simple Injector?
OR more specifically:
How can I instantiate multiple MathHelpers within the context of the Simple Injector Scope?
I've read up on http://simpleinjector.readthedocs.org/en/latest/lifetimes.html
and read and followed the SO answer https://stackoverflow.com/a/29808487/625113 however,
it seems either everything can be transient or scoped but not certain specific objects scoped and the rest transient (which seems odd).
Update 1
The following with Simple Injector will achieve the SharedService result, but if I want ProductService and CompositeService to also have a scoped lifetime it wont work:
cont.RegisterLifetimeScope<SharedService>();
cont.Register<MathHelper>();
cont.Register<ProductService>();
cont.Register<CompositeService>();
using (cont.BeginLifetimeScope())
{
var compositeSvc = cont.GetInstance<CompositeService>();
compositeSvc.Process();
}
If I register either or both of the ProductService or CompositeService as RegisterLifetimeScope I get a Lifetime mismatch exception. ie
cont.RegisterLifetimeScope<SharedService>();
cont.Register<MathHelper>();
cont.RegisterLifetimeScope<ProductService>();
cont.Register<CompositeService>(); // or cont.RegisterLifetimeScope<CompositeService>();
using (cont.BeginLifetimeScope())
{
var compositeSvc = cont.GetInstance<CompositeService>(); // Exception thrown
compositeSvc.Process();
}
Throws an exception leading to this page: https://simpleinjector.readthedocs.org/en/latest/LifestyleMismatches.html
I can under that in relation to Singleton should be dependent on Transient and can infer a sort of understanding that the same could be said in this case that Simple Injector is warning that Scoped can't depend on Transient because Transient isn't managed within the scope.
So my question is more specifically how can I instantiate multiple MathHelpers within the context of the Simple Injector Scope?
Update 2 - Further background and example
Brief background - This situation arose as I have a 4 year old, 2-tier, WPF based application currently using Ninject which has the bloated mixed Service architecture that #Steven describes
in his blog series (ie the Services have become a mash of mixed, semi-related, command and queries). Most of these services are a good candidate for separating out into
ICommandHandler/IQueryHandler architecture...but you can't do things overnight, so first crack was to convert from Ninject to SimpleInjector (yes I know Ninject can do the same thing in regards to this architecture
but there are other reasons for moving to SimpleInjector).
As far as "scoping" the dependency resolution, a "scope" (in this application) is considered to be for the life of a form so one DbContext (like the SharedService in the example above) is shared amoungst the
services that the form/viewModel require and MOST of the services are per scope with some injected services or helper classes needing to be injected as Transient.
This (to me) is analogous to Mark Seemann's hand-coded example from http://blog.ploeh.dk/2014/06/03/compile-time-lifetime-matching/ where he has a Per Request (singleton-scoped) service which has
Transient objects injected into it.
Edit: I had misread Mark Seemann's example and was reading the code as if the BarController were a service. So whilst the BarController object composition is the same the lifetime is not. That said the SomeThreadUnsafeService could just as easily have a new SomeServiceThatMustBeTransient injected into it but, I stand corrected, his example doesn't do this.
Hence I was wanting to know how to do the object composition Mark Seemann does in Simple Injector but outside the context of web reqeusts (my assumption is that Simple Injector's
Per web request scoping is in essence a specific type of Lifetime Scoping).
To address #Steve and #Ric .net's comment and answer, I can see that there is the potential to end up with the scenario where 2 different services use another, shared service that uses a transient object (storing state) and the supposedly transient object becomes a
Singleton Scoped object in the context of "some" of those services. eg
public class SingletonScopedService1
{
private readonly TransientX _transientA;
public SingletonScopedService1(TransientX transientA)
{
_transientA = transientA;
}
public void PokeTransient()
{
_transientA.Poke();
}
}
public class SingletonScopedService2
{
private readonly SingletonScopedService1 _service1;
private readonly TransientX _transientB;
public SingletonScopedService2(SingletonScopedService1 service1, TransientX transientB)
{
_service1 = service1;
_transientB = transientB;
}
public void GoFishing()
{
_service1.PokeTransient();
// This TransientX instance isn't affected
_transientB.Poke();
}
}
public class SingletonService3
{
private readonly SingletonScopedService1 _service1;
public SingletonService3(SingletonScopedService1 service1)
{
_service1 = service1;
}
public void DoSomething()
{
_service1.PokeTransient();
}
}
If DoSomething() is called on SingletonScopedService3 and GoFishing() is called on SingletonScopedService2 (and assuming TransientX maintains state) then results "may" be unexpected depending on the purpose of TransientX.
So I'm happy to accept this since the application is operating as expected (but also accept that the current composition is fragile).
With that said, can my original composition or Mark Seemann's example be registered with Simple Injector with the required life-times or is it strictly not possible by design and better to manually compose the object
graph (or inject a Func as #Ric .net suggests) for the instances where this is required until further refactoring/hardening can be done?
Update 3 - Conclusion
Whilst Ninject allows you to register my original composition like:
var kernel = new StandardKernel();
kernel.Bind<SharedService>().ToSelf().InCallScope();
kernel.Bind<MathHelper>().ToSelf();
kernel.Bind<ProductService>().ToSelf().InCallScope();
kernel.Bind<CompositeService>().ToSelf().InCallScope();
Simple Injector by design does not and I believe my second example is an example as to why.
FYI: In my real-world case, for the few instances that the object graph had this, I've manually constructed the graph (just to get switched to Simple Injector) with the intent on refactoring these potential issues out.
As explained in the linked SO question what the Lifestyle Mismatch exception is basically saying is that you're creating a so called captive dependency when you let a object depend on another object which has a shorter lifestyle.
While it maybe sounds odd to you, a captive dependency is:
A real life problem which, if undetected, would typically lead to very strange bugs which are very hard to debug
A sign, as indicated by Steven, that the service has some kind of state which is never a good sign
If MathHelper has mutable state and therefore needs to be injected in other services as transient, MathHelper has become some sort of 'runtime data'. And injecting runtime data is an anti-pattern.
This blogpost describes in detail what the problem is with runtime data and how to solve this. Solving your problem as described there is the way to go!
Because you did not specify the implementation details of MathHelper, it is hard to give you some advice how you should refactor MathHelper. So the only advice I can give you is, let runtime data or 'state' flow through the system as messages. You can read about message based design here and here.
There are however several other options, which will work but aren't good design IMO. So the advice is not to use these, but to be complete:
Instead of injecting MathHelper as a transient you could inject a MathHelperProvider or even simpler inject a Func<MathHelper> which you could register as singleton:
container.RegisterSingleton<Func<MathHelper>>(() => container.GetInstance<MathHelper>());
Notice that by registering a delegate you will make the container blind. It won't be able to warn you of misconfigurations in this part of the object graph anymore.
The other solutions I had in mind are so ugly in its design, that after writing them, I decided to leave them out of this answer!
If you would add some details about why MathHelper needs to be transient, I could give you some advice where you could make adjustments to make it scoped or even better: singleton.

Are Func<T> parameters in constructor slowing down my IoC resolving?

I'm trying to improve the performance of my IoC container. We are using Unity and SimpleInjector and we have a class with this constructor:
public AuditFacade(
IIocContainer container,
Func<IAuditManager> auditManagerFactory,
Func<ValidatorFactory> validatorCreatorFactory,
IUserContext userContext,
Func<ITenantManager> tenantManagerFactory,
Func<IMonitoringComponent> monitoringComponentFactory)
: base(container, auditManagerFactory, GlobalContext.CurrentTenant,
validatorCreatorFactory, userContext, tenantManagerFactory)
{
_monitoringComponent = new Lazy<IMonitoringComponent>(monitoringComponentFactory);
}
I also have another class with this constructor:
public AuditTenantComponent(Func<IAuditTenantRepository> auditTenantRepository)
{
_auditTenantRepository = new Lazy<IAuditTenantRepository>(auditTenantRepository);
}
I'm seeing that the second one gets resolved in 1 millisecond, most of the time, whereas the first one takes on average 50-60 milliseconds. I'm sure the reasoning for the slower one is because of the parameters, it has more parameters. But how can I improve the performance of this slower one? Is it the fact that we are using Func<T> as parameters? What can I change if it is causing the slowness?
There is possibly a lot to improve on your current design. These improvements can be placed in five different categories, namely:
Possible abuse of base classes
Use of Service Locator anti-pattern
Use of Ambient Context anti-pattern
Leaky abstractions
Doing too much in injection constructors
Possible abuse of base classes
The general consensus is that you should prefer composition over inheritance. Inheritance is often overused and often adds more complexity compared to using composition. With inheritance the derived class is strongly coupled to the base class implementation. I often see a base class being used as practical utility class containing all sorts of helper methods for cross-cutting concerns and other behavior that some of the derived classes may need.
An often better approach is to remove the base class all together and inject a service into the implementation (the AuditFacade class in your case) that exposed just the functionality that the service needs. Or in case of cross-cutting concerns, don't inject that behavior at all, but wrap the implementation with a decorator that extends the class'es behavior with cross-cutting concerns.
In your case, I think the complication is clearly happening, since 6 out of 7 injected dependencies are not used by the implementation, but are only passed on to the base class. In other words, those 6 dependencies are implementation details of the base class, while the implementation still is forced to know about them. By abstracting (part of) that base class behind a service, you can minimize the number of dependencies that AuditFacade needs to two dependencies: the Func<IMonitoringComponent> and the new abstraction. The implementation behind that abstraction will have 6 constructor dependencies, but the AuditFacade (and other implementations) are oblivious to that.
Use of Service Locator anti-pattern
The AuditFacade depends on an IIocContainer abstraction and this is very like an implementation of the Service Locator pattern. Service Locator should be considered an anti-pattern because:
it hides a class' dependencies, causing run-time errors instead of
compile-time errors, as well as making the code more difficult to
maintain because it becomes unclear when you would be introducing a
breaking change.
There are always better alternatives to injecting your container or an abstraction over your container into application code. Do note that at some times you might want to inject the container into factory implementations, but at long as those are placed inside your Composition Root, there's no harm in that, since Service Locator is about roles, not mechanics.
Use of Ambient Context anti-pattern
The static GlobalContext.CurrentTenant property is an implementation of the Ambient Context anti-pattern. Mark Seemann and I write about this pattern in our book:
The problems with AMBIENT CONTEXT are related to the problems with SERVICE
LOCATOR. The main problems are:
The DEPENDENCY is hidden.
Testing becomes more difficult.
It becomes very hard to change the DEPENDENCY based on its context. [paragraph 5.3.3]
The use in this case is really weird IMO, because you grab the current tenant from some static property from inside your constructor to pass it on to the base class. Why doesn't the base class call that property itself?
But no one should call that static property. The use of those static properties makes your code harder to read and maintain. It makes unit testing harder and since your code base will usually be littered with calls to such static, it becomes a hidden dependency; it has the same downsides as the use of Service Locator.
Leaky abstractions
A Leaky Abstraction is a Dependency Inversion Principle violation, where the abstraction violates the second part of the principle, namely:
B. Abstractions should not depend on details. Details should depend on
abstractions.
Although Lazy<T> is not abstractions by itself (Lazy<T> is a concrete type), it can become leaky abstraction when used as constructor argument. For instance, if you are injecting an Lazy<IMonitoringComponent> instead of an IMonitoringComponent directly (which is what you are basically doing in your code), the new Lazy<IMonitoringComponent> dependency leaks implementation details. This Lazy<IMonitoringComponent> communicates to the consumer that the used IMonitoringComponent implementation is expensive or time consuming to create. But why should the consumer care about this?
But there are more problems with this. If at one point in time the used IUserContext implementation becomes costly to create, we must start to make sweeping changes throughout the application (a violation of the Open/Closed Principle) because all IUserContext dependencies need to be changed to Lazy<IUserContext> and all consumers of that IUserContext must be changed to use userContext.Value. instead. And you'll have to change all your unit tests as well. And what happens if you forget to change one IUserContext reference to Lazy<IUserContext> or when you accidentally depend on IUserContext when you create a new class? You have a bug in your code, because at that point the user context implementation is created right away and this will cause a performance problem (this causes a problem, because that is the reason you are using Lazy<T> in the first place).
So why are we exactly making sweeping changes to our code base and polluting it with that extra layer of indirection? There is no reason for this. The fact that a dependency is costly to create is an implementation detail. You should hide it behind an abstraction. Here's an example:
public class LazyMonitoringComponentProxy : IMonitoringComponent {
private Lazy<IMonitoringComponent> component;
public LazyMonitoringComponentProxy(Lazy<IMonitoringComponent> component) {
this.component = component;
}
void IMonitoringComponent.MonitoringMethod(string someVar) {
this.component.Value.MonitoringMethod(someVar);
}
}
In this example we've hidden the Lazy<IMonitoringComponent> behind a proxy class. This allows us to replace the original IMonitoringComponent implementation with this LazyMonitoringComponentProxy without having to make any change to the rest of the applicaiton. With Simple Injector, we can register this type as follows:
container.Register<IMonitoringComponent>(() => new LazyMonitoringComponentProxy(
new Lazy<IMonitoringComponent>(container.GetInstance<CostlyMonitoringComp>));
And just as Lazy<T> can be abused as leaky abstraction, the same holds for Func<T>, especially when you're doing this for performance reasons. When applying DI correctly, there is most of the time no need to inject factory abstractions into your code such as Func<T>.
Do note that if you are injecting Lazy<T> and Func<T> all over the place, you are complicating your code base unneeded.
Doing too much in injection constructors
But besides Lazy<T> and Func<T> being leaky abstractions, the fact that you need them a lot is an indication of a problem with your application, because Injection Constructors should be simple. If constructors take a long time to run, your constructors are doing too much. Constructor logic is often hard to test and if such constructor makes a call to the database or requests data from HttpContext, verification of your object graphs becomes much harder to the point that you might skip verification all together. Skipping verification of the object graph is a terrible thing to do, because this forces you to click through the complete application to find out whether or not your DI container is configured correctly.
I hope this gives you some ideas about improving the design of your classes.
You can hook into Simple Injector's pipeline and add profiling, which allows you to spot which types are slow to create. Here's an extension method that you can use:
public struct ProfileData {
public readonly ExpressionBuildingEventArgs Info;
public readonly TimeSpan Elapsed;
public ProfileData(ExpressionBuildingEventArgs info, TimeSpan elapsed) {
this.Info = info;
this.Elapsed = elapsed;
}
}
static void EnableProfiling(Container container, List<ProfileData> profileLog) {
container.ExpressionBuilding += (s, e) => {
Func<Func<object>, object> profilingWrapper = creator => {
var watch = Stopwatch.StartNew();
var instance = creator.Invoke();
profileLog.Add(new ProfileData(e, watch.Elapsed));
return instance;
};
Func<object> instanceCreator =
Expression.Lambda<Func<object>>(e.Expression).Compile();
e.Expression = Expression.Convert(
Expression.Invoke(
Expression.Constant(profilingWrapper),
Expression.Constant(instanceCreator)),
e.KnownImplementationType);
};
}
And you can use this as follows:
var container = new Container();
// TODO: Your registrations here.
// Hook the profiler
List<ProfileData> profileLog = new List<ProfileData>(1000);
// Call this after all registrations.
EnableProfiling(container, profileLog);
// Trigger verification to allow everything to be precompiled.
container.Verify();
profileLog.Clear();
// Resolve a type:
container.GetInstance<AuditFacade>();
// Display resolve time in order of time.
var slowestFirst = profileLog.OrderByDescending(line => line.Elapsed);
foreach (var line in slowestFirst)
{
Console.WriteLine(string.Format("{0} ms: {1}",
line.Info.KnownImplementationType.Name,
line.Elapsed.TotalMilliseconds);
}
Do note that the shown times include the time it takes to resolve the dependencies, but this will probably allow you pretty easily what type causes the delay.
There are two important thing I want to note about the given code here:
This code will have severely negative impact on the performance of resolving object graphs, and
The code is NOT thread-safe.
So don't use it in your production environment.
Everything you do has a cost associated with it. Typically, more constructor parameters that are resolved recursively take longer than fewer parameters. But you must decide if the cost is ok or too high.
In your case, will the 50 ms cause a bottleneck? are you only creating 1 instance or are you puking them out in a tight loop? Just comparing the 1 ms with 50 ms might cause you to condemn the slower one, but if the user cannot tell that 50 ms passed and it doesn't cause a problem elsewhere in your app, why run through hoops to make it faster if you don't know it'll ever be needed?

Method injection (DI, .NET, IOC)

I am using .NET (MVC5, Web API etc). I understand constructor injection just about (fairly new to using it in anger).
I have a class with a method that has a dependency. I don't want to use constructor injection because then I will be creating the dependent object every time this class is instantiated (and most of the methods don't use this dependent object).
So I thought method injection sounded like it might be the thing. However I can't figure out how to do it (I am using Autofac).
So if my method is
void DoSomething(string x, int y)
and that method needs to use an implementation of IMyService, how do I do this without using the constructor injection?
The only method injection technique I have seen is one where effectively a method is called at instantiation. This doesn't seem to help my case, it still means that all instances create this dependency even if I am going to call a method that doesn't need it.
I'm sure it is something simple but I can't figure it out right now. Could you help me with an example please?
UPDATE
this is the crux of it. I like the idea of Lazy suggested by Jim and will try this. So is method injection as I suspected and if so I don't really understand the point of it - why use it instead of constructor injection?
public class MailService {
// lots of methods that don't need PlayerDataService
public void SendPlayersEmail() {
var service = new PlayerDataService();
var players = service.GetPlayers();
foreach(var player in players) {
SendEmail(player);
}
}
}
I don't want to use constructor injection because then I will be creating the dependent object every time this class is instantiated (and most of the methods don't use this dependent object).
There's the problem. Break that functionality out into a new class.
That is, at least in my experience, the best solution when a method does not fit into the rest of the class (or have dependencies that are not used anywhere else).
You should also consider that object allocation is pretty cheap, you need millions of allocations per second before the performance is hurt (unless you are using Ninject ;))
If the cost of instantiating your object during construction is an issue, you can wrap it in a Lazy<> to avoid unnecessary construction. This will cause your dependency to be constructed on the first call to the lazy's .Value.

Categories