Skip to content

Commit 91bd106

Browse files
committed
initial import of code from the StructureMap repo
1 parent 55abaac commit 91bd106

20 files changed

+1819
-0
lines changed

src/DynamicProxyInterceptorAcceptanceTests.cs

+1,014
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Castle.DynamicProxy;
2+
using System.Reflection;
3+
4+
namespace StructureMap.DynamicInterception
5+
{
6+
internal class Argument : IArgument
7+
{
8+
private readonly IInvocation _invocation;
9+
private readonly int _index;
10+
private object _value;
11+
12+
public Argument(IInvocation invocation, int index, object value, ParameterInfo parameterInfo)
13+
{
14+
_invocation = invocation;
15+
_index = index;
16+
_value = value;
17+
ParameterInfo = parameterInfo;
18+
}
19+
20+
public object Value
21+
{
22+
get { return _value; }
23+
set
24+
{
25+
_invocation.SetArgumentValue(_index, value);
26+
_value = value;
27+
}
28+
}
29+
30+
public ParameterInfo ParameterInfo { get; private set; }
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Castle.DynamicProxy;
2+
3+
namespace StructureMap.DynamicInterception
4+
{
5+
internal class AsyncWrapperInterceptor : IInterceptor
6+
{
7+
private readonly IAsyncInterceptionBehavior _interceptionBehavior;
8+
9+
public AsyncWrapperInterceptor(IAsyncInterceptionBehavior interceptionBehavior)
10+
{
11+
_interceptionBehavior = interceptionBehavior;
12+
}
13+
14+
public void Intercept(IInvocation invocation)
15+
{
16+
var methodInvocation = new MethodInvocation(invocation);
17+
var methodInvocationResultTask = _interceptionBehavior.InterceptAsync(methodInvocation);
18+
19+
if (!ReflectionHelper.IsTask(methodInvocation.MethodInfo.ReturnType))
20+
{
21+
var methodInvocationResult = ReflectionHelper.GetTaskResult(methodInvocationResultTask);
22+
23+
invocation.ReturnValue = methodInvocationResult.GetReturnValueOrThrow();
24+
}
25+
else
26+
{
27+
var actualReturnType = methodInvocation.ActualReturnType;
28+
invocation.ReturnValue = actualReturnType == typeof(void)
29+
? ReflectionHelper.ConvertInvocationResultToTask(methodInvocationResultTask)
30+
: ReflectionHelper.ConvertInvocationResultToTask(actualReturnType,
31+
methodInvocationResultTask);
32+
}
33+
}
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using Castle.DynamicProxy;
2+
using StructureMap.Building.Interception;
3+
using StructureMap.TypeRules;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Linq.Expressions;
8+
9+
namespace StructureMap.DynamicInterception
10+
{
11+
public class DynamicProxyInterceptor<TPluginType> : FuncInterceptor<TPluginType>
12+
where TPluginType : class
13+
14+
{
15+
private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
16+
17+
private readonly string _description;
18+
19+
public DynamicProxyInterceptor(IEnumerable<Type> interceptionBehaviorTypes) : this(interceptionBehaviorTypes.ToArray())
20+
{
21+
}
22+
23+
public DynamicProxyInterceptor(params Type[] interceptionBehaviorTypes) : base(buildExpression(interceptionBehaviorTypes))
24+
{
25+
_description = buildDescription(interceptionBehaviorTypes);
26+
}
27+
28+
public DynamicProxyInterceptor(IEnumerable<IInterceptionBehavior> interceptionBehaviors) : this(interceptionBehaviors.ToArray())
29+
{
30+
}
31+
32+
private DynamicProxyInterceptor(IInterceptionBehavior[] interceptionBehaviors) : base(buildExpression(interceptionBehaviors))
33+
{
34+
_description = buildDescription(interceptionBehaviors.Select(b => b.GetType()));
35+
}
36+
37+
private static Expression<Func<IContext, TPluginType, TPluginType>> buildExpression(IEnumerable<Type> interceptionBehaviorTypes)
38+
{
39+
return (context, instance) => proxyGenerator.CreateInterfaceProxyWithTarget(
40+
instance,
41+
interceptionBehaviorTypes
42+
.Select(t => WrapInterceptorBehavior((IInterceptionBehavior)context.GetInstance(t)))
43+
.ToArray()
44+
);
45+
}
46+
47+
private static Expression<Func<TPluginType, TPluginType>> buildExpression(IEnumerable<IInterceptionBehavior> interceptionBehaviors)
48+
{
49+
return instance => proxyGenerator.CreateInterfaceProxyWithTarget(
50+
instance,
51+
interceptionBehaviors.Select(WrapInterceptorBehavior).ToArray()
52+
);
53+
}
54+
55+
private static string buildDescription(IEnumerable<Type> interceptionBehaviorTypes)
56+
{
57+
return string.Format("DynamicProxyInterceptor of {0} with interception behaviors: {1}",
58+
typeof(TPluginType).GetFullName(),
59+
string.Join(", ", interceptionBehaviorTypes.Select(t => t.GetFullName())));
60+
}
61+
62+
private static Castle.DynamicProxy.IInterceptor WrapInterceptorBehavior(IInterceptionBehavior behavior)
63+
{
64+
var syncBehavior = behavior as ISyncInterceptionBehavior;
65+
if (syncBehavior != null)
66+
{
67+
return new SyncWrapperInterceptor(syncBehavior);
68+
}
69+
70+
var asyncBehavior = behavior as IAsyncInterceptionBehavior;
71+
if (asyncBehavior != null)
72+
{
73+
return new AsyncWrapperInterceptor(asyncBehavior);
74+
}
75+
76+
throw new StructureMapException(string.Format(
77+
"{0} does not implement neither ISyncInterceptionBehavior nor IAsyncInterceptionBehavior",
78+
behavior.GetType().GetFullName()));
79+
}
80+
81+
public override string Description
82+
{
83+
get { return _description; }
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using StructureMap.Building.Interception;
2+
using StructureMap.Pipeline;
3+
using StructureMap.TypeRules;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
8+
namespace StructureMap.DynamicInterception
9+
{
10+
public class DynamicProxyInterceptorPolicy : IInterceptorPolicy
11+
{
12+
private static readonly Func<Type, Instance, bool> TrueFilter = (type, instance) => true;
13+
14+
private readonly Func<Type, Instance, bool> _filter;
15+
private readonly object[] _interceptionBehaviors;
16+
17+
public DynamicProxyInterceptorPolicy(Func<Type, Instance, bool> filter, params IInterceptionBehavior[] interceptionBehaviors)
18+
{
19+
_filter = filter ?? TrueFilter;
20+
_interceptionBehaviors = interceptionBehaviors;
21+
}
22+
23+
public DynamicProxyInterceptorPolicy(Func<Type, bool> filter, params IInterceptionBehavior[] interceptionBehaviors)
24+
: this((type, instance) => filter(type), interceptionBehaviors)
25+
{
26+
}
27+
28+
public DynamicProxyInterceptorPolicy(Func<Instance, bool> filter, params IInterceptionBehavior[] interceptionBehaviors)
29+
: this((type, instance) => filter(instance), interceptionBehaviors)
30+
{
31+
}
32+
33+
public DynamicProxyInterceptorPolicy(params IInterceptionBehavior[] interceptionBehaviors)
34+
: this(TrueFilter, interceptionBehaviors)
35+
{
36+
}
37+
38+
public DynamicProxyInterceptorPolicy(Func<Type, Instance, bool> filter, params Type[] interceptionBehaviorTypes)
39+
{
40+
_filter = filter ?? TrueFilter;
41+
_interceptionBehaviors = interceptionBehaviorTypes;
42+
}
43+
44+
public DynamicProxyInterceptorPolicy(Func<Type, bool> filter, params Type[] interceptionBehaviorTypes)
45+
: this((type, instance) => filter(type), interceptionBehaviorTypes)
46+
{
47+
}
48+
49+
public DynamicProxyInterceptorPolicy(Func<Instance, bool> filter, params Type[] interceptionBehaviorTypes)
50+
: this((type, instance) => filter(instance), interceptionBehaviorTypes)
51+
{
52+
}
53+
54+
public DynamicProxyInterceptorPolicy(params Type[] interceptionBehaviorTypes)
55+
: this(TrueFilter, interceptionBehaviorTypes)
56+
{
57+
}
58+
59+
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
60+
{
61+
if (_filter(pluginType, instance))
62+
{
63+
var interceptorType = typeof(DynamicProxyInterceptor<>).MakeGenericType(pluginType);
64+
var interceptor = (IInterceptor)Activator.CreateInstance(interceptorType, new object[] { _interceptionBehaviors });
65+
yield return interceptor;
66+
}
67+
}
68+
69+
public string Description
70+
{
71+
get
72+
{
73+
return string.Format("Decorate with dynamic proxy classes using the following interception behaviors: {0}",
74+
string.Join(", ", _interceptionBehaviors.Select(b => (b as Type ?? b.GetType()).GetFullName())));
75+
}
76+
}
77+
}
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Reflection;
2+
3+
namespace StructureMap.DynamicInterception
4+
{
5+
public interface IArgument
6+
{
7+
object Value { get; set; }
8+
9+
ParameterInfo ParameterInfo { get; }
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Threading.Tasks;
2+
3+
namespace StructureMap.DynamicInterception
4+
{
5+
public interface IAsyncInterceptionBehavior : IInterceptionBehavior
6+
{
7+
Task<IMethodInvocationResult> InterceptAsync(IAsyncMethodInvocation methodInvocation);
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Threading.Tasks;
2+
3+
namespace StructureMap.DynamicInterception
4+
{
5+
public interface IAsyncMethodInvocation : IMethodInvocation
6+
{
7+
Task<IMethodInvocationResult> InvokeNextAsync();
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace StructureMap.DynamicInterception
2+
{
3+
public interface IInterceptionBehavior
4+
{
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
5+
namespace StructureMap.DynamicInterception
6+
{
7+
public interface IMethodInvocation
8+
{
9+
IList<IArgument> Arguments { get; }
10+
11+
IArgument GetArgument(string name);
12+
13+
object TargetInstance { get; }
14+
15+
MethodInfo MethodInfo { get; }
16+
17+
MethodInfo InstanceMethodInfo { get; }
18+
19+
Type ActualReturnType { get; }
20+
21+
IMethodInvocationResult CreateResult(object value);
22+
23+
IMethodInvocationResult CreateExceptionResult(Exception e);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace StructureMap.DynamicInterception
4+
{
5+
public interface IMethodInvocationResult
6+
{
7+
bool Successful { get; }
8+
9+
object ReturnValue { get; }
10+
11+
Exception Exception { get; }
12+
13+
object GetReturnValueOrThrow();
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace StructureMap.DynamicInterception
2+
{
3+
public interface ISyncInterceptionBehavior : IInterceptionBehavior
4+
{
5+
IMethodInvocationResult Intercept(ISyncMethodInvocation methodInvocation);
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace StructureMap.DynamicInterception
2+
{
3+
public interface ISyncMethodInvocation : IMethodInvocation
4+
{
5+
IMethodInvocationResult InvokeNext();
6+
}
7+
}

0 commit comments

Comments
 (0)