Last active
June 21, 2018 14:45
-
-
Save vas6ili/dfeced5cebaff9e080e9c0db3546476e to your computer and use it in GitHub Desktop.
Deconstruction in Service Locator pattern example
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 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