This repository was archived by the owner on Jul 13, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathContainerResolverCache.cs
More file actions
65 lines (56 loc) · 2.02 KB
/
ContainerResolverCache.cs
File metadata and controls
65 lines (56 loc) · 2.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using SimpleStack.Interfaces;
using Funq;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
namespace SimpleStack
{
public class ContainerResolveCache : ITypeFactory
{
private Container container;
private static Dictionary<Type, Func<Container, object>> resolveFnMap = new Dictionary<Type, Func<Container, object>>();
public ContainerResolveCache(Container container)
{
this.container = container;
}
private Func<Container, object> GenerateServiceFactory(Type type, bool tryResolve)
{
var resolveType = tryResolve ? "TryResolve" : "Resolve";
var containerParam = Expression.Parameter(typeof(Container), "container");
var resolveInstance = Expression.Call(containerParam, resolveType, new[] { type }, new Expression[0]);
var resolveObject = Expression.Convert(resolveInstance, typeof(object));
return Expression.Lambda<Func<Container, object>>(resolveObject, containerParam).Compile();
}
/// <summary>
/// Creates instance using straight Resolve approach.
/// This will throw an exception if resolution fails
/// </summary>
public object CreateInstance(Type type)
{
return CreateInstance(type, false);
}
/// <summary>
/// Creates instance using the TryResolve approach if tryResolve = true.
/// Otherwise uses Resolve approach, which will throw an exception if resolution fails
/// </summary>
public object CreateInstance(Type type, bool tryResolve)
{
Func<Container, object> resolveFn;
if (!resolveFnMap.TryGetValue(type, out resolveFn))
{
resolveFn = GenerateServiceFactory(type, tryResolve);
//Support for multiple threads is needed
Dictionary<Type, Func<Container, object>> snapshot, newCache;
do
{
snapshot = resolveFnMap;
newCache = new Dictionary<Type, Func<Container, object>>(resolveFnMap);
newCache[type] = resolveFn;
} while (!ReferenceEquals(
Interlocked.CompareExchange(ref resolveFnMap, newCache, snapshot), snapshot));
}
return resolveFn(this.container);
}
}
}