Skip to content

Instantly share code, notes, and snippets.

@vas6ili
Last active June 21, 2018 14:45
Show Gist options
  • Save vas6ili/dfeced5cebaff9e080e9c0db3546476e to your computer and use it in GitHub Desktop.
Save vas6ili/dfeced5cebaff9e080e9c0db3546476e to your computer and use it in GitHub Desktop.
Deconstruction in Service Locator pattern example
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Runtime.CompilerServices;
namespace DisposableValueTuples
{
[MemoryDiagnoser]
public class Benchmark
{
private readonly IIocContainer _container = new IocContainer();
[Benchmark(Baseline = true)]
public void Manual()
{
IFoo foo = null;
IBar bar = null;
IXyz xyz = null;
try
{
foo = _container.Resolve<IFoo>();
bar = _container.Resolve<IBar>();
xyz = _container.Resolve<IXyz>();
}
finally
{
_container.Release(foo);
_container.Release(bar);
_container.Release(xyz);
}
}
[Benchmark]
public void UsingValueTuplesScope()
{
using (var deps = _container.ResolveScoped<IFoo, IBar, IXyz>())
{
var (foo, bar, xyz) = deps;
}
}
[Benchmark]
public void UsingManualScope()
{
using (var deps = _container.ResolveScoped2<IFoo, IBar, IXyz>())
{
var (foo, bar, xyz) = deps;
}
}
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<Benchmark>();
//var container = new IocContainer();
//using (var deps = container.ResolveScoped<IFoo, IBar, IXyz>())
//{
// var (foo, bar, xyz) = deps;
//}
}
}
public interface IFoo { }
public interface IBar { }
public interface IXyz { }
public class Impl : IFoo, IBar, IXyz { }
public interface IIocContainer
{
T Resolve<T>() where T : class;
void Release<T>(T item) where T : class;
}
public class IocContainer : IIocContainer
{
public void Release<T>(T item) where T : class { }
public T Resolve<T>() where T : class => new Impl() as T;
}
public static class IocContainerExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DependencyScopeValueTuple<T1, T2, T3> ResolveScoped<T1, T2, T3>(this IIocContainer container)
where T1 : class
where T2 : class
where T3 : class
{
var deps = (
container.Resolve<T1>(),
container.Resolve<T2>(),
container.Resolve<T3>()
);
return new DependencyScopeValueTuple<T1, T2, T3>(container, deps);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DependencyScopeManual<T1, T2, T3> ResolveScoped2<T1, T2, T3>(this IIocContainer container)
where T1 : class
where T2 : class
where T3 : class
{
return new DependencyScopeManual<T1, T2, T3>(
container,
container.Resolve<T1>(),
container.Resolve<T2>(),
container.Resolve<T3>()
);
}
}
public struct DependencyScopeValueTuple<T1, T2, T3> : IDisposable
where T1 : class
where T2 : class
where T3 : class
{
private readonly (T1, T2, T3) _items;
private readonly IIocContainer _container;
public DependencyScopeValueTuple(IIocContainer container, (T1, T2, T3) items)
{
_items = items;
_container = container;
}
public void Dispose()
{
_container.Release(_items.Item1);
_container.Release(_items.Item2);
_container.Release(_items.Item3);
}
public void Deconstruct(out T1 item1, out T2 item2, out T3 item3)
{
item1 = _items.Item1;
item2 = _items.Item2;
item3 = _items.Item3;
}
}
public struct DependencyScopeManual<T1, T2, T3> : IDisposable
where T1 : class
where T2 : class
where T3 : class
{
private readonly IIocContainer _container;
private readonly T1 _item1;
private readonly T2 _item2;
private readonly T3 _item3;
public DependencyScopeManual(IIocContainer container, T1 item1, T2 item2, T3 item3)
{
_container = container;
_item1 = item1;
_item2 = item2;
_item3 = item3;
}
public void Dispose()
{
_container.Release(_item1);
_container.Release(_item2);
_container.Release(_item3);
}
public void Deconstruct(out T1 item1, out T2 item2, out T3 item3)
{
item1 = _item1;
item2 = _item2;
item3 = _item3;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment