Last active
March 16, 2023 09:26
-
-
Save davidfowl/86490126bf4a4f1301aa5bb049d8d244 to your computer and use it in GitHub Desktop.
DI under the hood. This is what DI containers automate for you
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
namespace PureDI | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// Create the singletons once | |
var singletons = new SingletonDependencies(); | |
// Create a transient object | |
var myClass = new MyTransientClass1(singletons.Singleton1, singletons.Singleton2, new MyTransientClass2(new MyTransientClass3())); | |
// Create another transient object | |
var otherClass = new MyTransientClass2(new MyTransientClass3()); | |
} | |
static void WebRequest(SingletonDependencies singletons) | |
{ | |
// Make a per request scope with access to the singletons | |
var requestScope = new ScopedDependencies(singletons); | |
// Create a controller passing the request scoped dependency and transient dependency | |
var controller = new MyController(requestScope.Scoped1); | |
} | |
} | |
public class MyController | |
{ | |
public IScoped1 Scoped1 { get; } | |
public MyController(IScoped1 scoped1) | |
{ | |
Scoped1 = scoped1; | |
} | |
} | |
// Transient dependencies | |
public interface IMyTransientClass1 { } | |
public interface IMyTransientClass2 { } | |
public interface IMyTransientClass3 { } | |
public class MyTransientClass1 : IMyTransientClass1 | |
{ | |
public ISingleton1 Singleton1 { get; } | |
public ISingleton2 Singleton2 { get; } | |
public IMyTransientClass2 MyTransientClass2 { get; } | |
public MyTransientClass1(ISingleton1 singleton1, ISingleton2 singleton2, IMyTransientClass2 myOtherClass) | |
{ | |
Singleton1 = singleton1; | |
Singleton2 = singleton2; | |
MyTransientClass2 = myOtherClass; | |
} | |
} | |
public class MyTransientClass2 : IMyTransientClass2 | |
{ | |
public IMyTransientClass3 MyTransientClass3 { get; } | |
public MyTransientClass2(IMyTransientClass3 anotherClass) | |
{ | |
MyTransientClass3 = anotherClass; | |
} | |
} | |
public class MyTransientClass3 : IMyTransientClass3 | |
{ | |
} | |
// Scoped dependencies | |
public interface IScoped1 { } | |
public interface IScoped2 { } | |
public interface IScoped3 { } | |
public class Scoped1 : IScoped1 | |
{ | |
} | |
public class Scoped2 : IScoped2 | |
{ | |
public IScoped1 Scoped1 { get; } | |
public Scoped2(IScoped1 scoped1) | |
{ | |
Scoped1 = scoped1; | |
} | |
} | |
public class Scoped3 : IScoped3 | |
{ | |
public IMyTransientClass1 MyTransientClass1 { get; } | |
public IScoped2 Scoped2 { get; } | |
public Scoped3(IMyTransientClass1 myTransientClass1, IScoped2 scoped2) | |
{ | |
MyTransientClass1 = myTransientClass1; | |
Scoped2 = scoped2; | |
} | |
} | |
// The class that represents all scoped dependencies | |
public class ScopedDependencies | |
{ | |
private IScoped1 _scoped1; | |
private IScoped2 _scoped2; | |
private IScoped3 _scoped3; | |
private object _lockObject = new object(); | |
private readonly SingletonDependencies _singletons; | |
public ScopedDependencies(SingletonDependencies singletons) | |
{ | |
_singletons = singletons; | |
} | |
public IScoped1 Scoped1 => LazyInitializer.EnsureInitialized(ref _scoped1, ref _lockObject, () => new Scoped1()); | |
public IScoped2 Scoped2 => LazyInitializer.EnsureInitialized(ref _scoped2, ref _lockObject, () => new Scoped2(Scoped1)); | |
public IScoped3 Scoped3 => LazyInitializer.EnsureInitialized(ref _scoped3, ref _lockObject, () => new Scoped3( | |
new MyTransientClass1( | |
_singletons.Singleton1, | |
_singletons.Singleton2, | |
new MyTransientClass2(new MyTransientClass3())), | |
Scoped2)); | |
} | |
// Singleton dependencies | |
public interface ISingleton1 { } | |
public interface ISingleton2 { } | |
public class Singleton1 : ISingleton1 | |
{ | |
public ISingleton2 Singleton2 { get; } | |
public Singleton1(ISingleton2 singleton2) | |
{ | |
Singleton2 = singleton2; | |
} | |
} | |
public class Singleton2 : ISingleton2 { } | |
// The class that represents all singleton dependencies | |
public class SingletonDependencies | |
{ | |
private ISingleton1 _singleton1; | |
private ISingleton2 _singleton2; | |
private object _lockObject = new object(); | |
public ISingleton1 Singleton1 => LazyInitializer.EnsureInitialized(ref _singleton1, ref _lockObject, () => new Singleton1(Singleton2)); | |
public ISingleton2 Singleton2 => LazyInitializer.EnsureInitialized(ref _singleton2, ref _lockObject, () => new Singleton2()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://github.com/dotnet/extensions/issues/2207