Skip to content

Instantly share code, notes, and snippets.

@KodrAus
Forked from davidfowl/PureDI.cs
Last active January 20, 2020 07:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KodrAus/f10ba6c61f030909acf730f9b9cfb749 to your computer and use it in GitHub Desktop.
Save KodrAus/f10ba6c61f030909acf730f9b9cfb749 to your computer and use it in GitHub Desktop.
DI under the hood. This is what DI containers automate for you
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
using 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 : IDisposable
{
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));
public void Dispose()
{
if (_scoped1 is IDisposable disposable1)
disposable1?.Dispose();
if (_scoped2 is IDisposable disposable2)
disposable2?.Dispose();
if (_scoped3 is IDisposable disposable3)
disposable3?.Dispose();
}
}
// 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