YairHalberstadt / stronginject

compile time dependency injection for .NET
MIT License
845 stars 24 forks source link

Inject Func<Owned<T>> parameters #140

Closed jnm2 closed 3 years ago

jnm2 commented 3 years ago

This enables classes to choose when and how many times to get a reference to a dependency and when to release a dependency while being perfectly agnostic about the lifespan of the dependency before and after this (singleton, transient, pooled, etc).

It also enables a class A to obtain dependency B which causes dependency C to be created. Dependency B knows about dependency C, but class A does not know about dependency C and cannot properly release or dispose it when it is finished using dependency B. Dependency B also can't assume that it owns and should dispose dependency C when it is itself disposed. The solution is to inject Func<Owned<B>> into A instead of Func<B>.

A comparable feature is Castle Windsor's Typed Factories feature where Windsor auto-implements any factory-like interface that you declare yourself and register as a typed factory. The T IFactory<T>.Resolve() call is logically equivalent to Owned<T> Func<Owned<T>>.Invoke() and the void IFactory<T>.Release(T) call is logically equivalent to void Owned<T>.Dispose().

I don't really have an opinion on whether injecting bare Owned<T> should be supported, rather than injecting a delegate with Owned<T> as the return type.

YairHalberstadt commented 3 years ago

Sounds great!

The way I would recommend this be implemented is that an Owned<T> creates it's own scope, exactly like a Func<T>, but unlike a Func<T> the disposeAction is not stored for later, but given as one of the parameters to the Owned<T>.

I think this should be fairly straightforward conceptually, but there'll be lots of places which will need changing in the code.