forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunqEasyRegistrationHelper.cs
More file actions
69 lines (57 loc) · 2.4 KB
/
FunqEasyRegistrationHelper.cs
File metadata and controls
69 lines (57 loc) · 2.4 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
65
66
67
68
69
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Funq;
namespace ServiceStack.ServiceHost.Tests.Examples
{
/// <summary>
/// Funq helper for easy registration.
/// </summary>
public static class FunqEasyRegistrationHelper
{
/// <summary>
/// Register a service with the default, look-up-all_dependencies-from-the-container behavior.
/// </summary>
/// <typeparam name="interfaceT">interface type</typeparam>
/// <typeparam name="implT">implementing type</typeparam>
/// <param name="container">Funq container</param>
public static void EasyRegister<interfaceT, implT>(this Container container) where implT : interfaceT
{
var lambdaParam = Expression.Parameter(typeof(Container), "ref_to_the_container_passed_into_the_lambda");
var constructorExpression = BuildImplConstructorExpression<implT>(lambdaParam);
var compiledExpression = CompileInterfaceConstructor<interfaceT>(lambdaParam, constructorExpression);
container.Register(compiledExpression);
}
private static readonly MethodInfo FunqContainerResolveMethod;
static FunqEasyRegistrationHelper()
{
FunqContainerResolveMethod = typeof(Container).GetMethod("Resolve", new Type[0]);
}
private static NewExpression BuildImplConstructorExpression<implT>(Expression lambdaParam)
{
var ctorWithMostParameters = GetConstructorWithMostParameters<implT>();
var constructorParameterInfos = ctorWithMostParameters.GetParameters();
var regParams = constructorParameterInfos.Select(pi => GetParameterCreationExpression(pi, lambdaParam));
return Expression.New(ctorWithMostParameters, regParams.ToArray());
}
private static Func<Container, interfaceT> CompileInterfaceConstructor<interfaceT>(ParameterExpression lambdaParam, Expression constructorExpression)
{
var constructorLambda = Expression.Lambda<Func<Container, interfaceT>>(constructorExpression, lambdaParam);
return constructorLambda.Compile();
}
private static ConstructorInfo GetConstructorWithMostParameters<implT>()
{
return typeof(implT)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length)
.Where(ctor => !ctor.IsStatic)
.Last();
}
private static MethodCallExpression GetParameterCreationExpression(ParameterInfo pi, Expression lambdaParam)
{
var method = FunqContainerResolveMethod.MakeGenericMethod(pi.ParameterType);
return Expression.Call(lambdaParam, method);
}
}
}