User: xtoff
Date: 2009/11/26 03:41 PM
Added:
/DynamicProxy/trunk/src/Castle.DynamicProxy/
CompositionInvocation.cs, InheritanceInvocation.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
ClassInvocationTypeGenerator.cs
Modified:
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
InvocationMethodInvocationTargetTestCase.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenInterfaces/
GenInterfaceWithGenericTypes.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/
AbstractInvocation.cs, Castle.DynamicProxy-vs2008.csproj, InvocationHelper.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
ClassProxyTargetContributor.cs, InterfaceProxyTargetContributor.cs,
InterfaceProxyWithoutTargetContributor.cs, MixinContributor.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
CacheKey.cs, ClassProxyGenerator.cs, InterfaceInvocationTypeGenerator.cs,
InterfaceMethodGenerator.cs, InvocationTypeGenerator.cs,
MethodWithCallbackGenerator.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
InvocationMethods.cs
Log:
- changed behavior of MethodInvocationTarget so that it points to method on
proxied class rather than on proxy for class proxies.
File Changes:
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/
=======================================================
File [modified]: AbstractInvocation.cs
Delta lines: +3 -0
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Castle.DynamicProxy-vs2008.csproj
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Castle.DynamicProxy-vs2008.csproj
2009-11-26 22:41:19 UTC (rev 6364)
@@ -99,6 +99,7 @@
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="CompositionInvocation.cs" />
<Compile Include="Contributors\CompositeTypeContributor.cs" />
<Compile Include="Contributors\InterfaceMethodGeneratorBase.cs" />
<Compile Include="Generators\AttributeDisassembler.cs" />
@@ -110,6 +111,7 @@
<Compile Include="Contributors\Delegates.cs" />
<Compile Include="Contributors\EmptyMixinContributor.cs" />
<Compile Include="Contributors\InterfaceProxyWithoutTargetContributor.cs"
/>
+ <Compile Include="Generators\ClassInvocationTypeGenerator.cs" />
<Compile
Include="Generators\Emitters\SimpleAST\NullCoalescingOperatorExpression.cs" />
<Compile Include="Generators\GeneratorUtil.cs" />
<Compile Include="Generators\MethodWithCallbackGenerator.cs" />
@@ -296,6 +298,7 @@
<Compile Include="Generators\PropertyToGenerate.cs" />
<Compile Include="Contributors\MembersCollector.cs" />
<Compile Include="Contributors\ProxyInstanceContributor.cs" />
+ <Compile Include="InheritanceInvocation.cs" />
<Compile Include="InternalsHelper.cs" />
<Compile Include="InvalidMixinConfigurationException.cs" />
File [modified]: Castle.DynamicProxy-vs2008.csproj
Delta lines: +116 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/CompositionInvocation.cs
(rev 0)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/CompositionInvocation.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -0,0 +1,116 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.DynamicProxy
+{
+ using System;
+ using System.Reflection;
+
+ using Castle.Core.Interceptor;
+
+ public abstract class CompositionInvocation : AbstractInvocation
+ {
+ protected object target;
+
+ protected CompositionInvocation(
+ object target,
+ object proxy,
+ IInterceptor[] interceptors,
+ MethodInfo proxiedMethod,
+ object[] arguments)
+ : base(proxy, interceptors, proxiedMethod, arguments)
+ {
+ this.target = target;
+ }
+
+ protected CompositionInvocation(
+ object target,
+ object proxy,
+ IInterceptor[] interceptors,
+ MethodInfo proxiedMethod,
+ object[] arguments,
+ IInterceptorSelector selector,
+ ref IInterceptor[] methodInterceptors)
+ : base(proxy, GetTargetType(target), interceptors,
proxiedMethod, arguments, selector, ref methodInterceptors)
+ {
+ this.target = target;
+ }
+
+ private static Type GetTargetType(object targetObject)
+ {
+ if (targetObject == null)
+ {
+ return null;
+ }
+ return targetObject.GetType();
+ }
+
+ protected void EnsureValidTarget()
+ {
+ string message;
+ if (target == null)
+ {
+ message = "This is a DynamicProxy2 error: the
interceptor attempted " +
+ "to 'Proceed' for method '" +
Method.ToString() + "' which has no target." +
+ " When calling method without target
there is no implementation to 'proceed' to " +
+ "and it is the responsibility of the
interceptor to mimic the implementation (set return value, out arguments etc)";
+ throw new NotImplementedException(message);
+ }
+
+ if (!ReferenceEquals(target, proxyObject))
+ {
+ return;
+ }
+ message = "This is a DynamicProxy2 error: target of
invocation has been set to the proxy itself. " +
+ "This may result in recursively calling the
method over and over again until stack overflow, which may destabilize your
program." +
+ "This usually signifies a bug in the calling
code. Make sure no interceptor sets proxy as its invocation target.";
+ throw new InvalidOperationException(message);
+ }
+
+ protected void EnsureValidProxyTarget(object newTarget)
+ {
+ if (newTarget == null)
+ {
+ throw new ArgumentNullException("newTarget");
+ }
+
+ if (!ReferenceEquals(newTarget, proxyObject))
+ {
+ return;
+ }
+ var message = "This is a DynamicProxy2 error: target of
proxy has been set to the proxy itself. " +
+ "This would result in
recursively calling proxy methods over and over again until stack overflow,
which may destabilize your program." +
+ "This usually signifies a bug
in the calling code. Make sure no interceptor sets proxy as its own target.";
+ throw new InvalidOperationException(message);
+ }
+
+ public override object InvocationTarget
+ {
+ get { return target; }
+ }
+
+ public override Type TargetType
+ {
+ get
+ {
+ return GetTargetType(target);
+ }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { return InvocationHelper.GetMethodOnObject(target,
Method); }
+ }
+ }
+}
File [added]: CompositionInvocation.cs
Delta lines: +4 -8
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyTargetContributor.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyTargetContributor.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -75,15 +75,11 @@
callback = CreateCallbackMethod(@class,
methodInfo, method.MethodOnTarget);
targetForInvocation = callback.DeclaringType;
}
- var invocation = new
InvocationTypeGenerator(targetForInvocation,
- method,
- callback,
-
false).Generate(@class, options, namingScope);
+ var invocation = new
ClassInvocationTypeGenerator(targetForInvocation,
+
method,
+
callback).Generate(@class, options, namingScope);
- return new MethodWithCallbackGenerator(method,
- invocation,
-
@class.GetField("__interceptors"),
- createMethod);
+ return new MethodWithCallbackGenerator(targetType,
method, invocation, @class.GetField("__interceptors"), createMethod);
}
File [added]: InheritanceInvocation.cs
Delta lines: +11 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/InvocationHelper.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/InvocationHelper.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -29,14 +29,23 @@
private static readonly SlimReaderWriterLock @lock = new
SlimReaderWriterLock();
- public static MethodInfo GetMethodOnTarget(object target,
MethodInfo proxiedMethod)
+ public static MethodInfo GetMethodOnObject(object target,
MethodInfo proxiedMethod)
{
if (target == null)
{
return null;
}
- Type type = target.GetType();
+ return GetMethodOnType(target.GetType(), proxiedMethod);
+ }
+
+ public static MethodInfo GetMethodOnType(Type type, MethodInfo
proxiedMethod)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+
Debug.Assert(proxiedMethod.DeclaringType.IsAssignableFrom(type),
"proxiedMethod.DeclaringType.IsAssignableFrom(type)");
File [modified]: InvocationHelper.cs
Delta lines: +35 -11
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/InvocationMethods.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/InvocationMethods.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -24,7 +24,7 @@
public static class InvocationMethods
{
public static readonly FieldInfo Target =
- typeof(AbstractInvocation).GetField("target",
BindingFlags.Instance | BindingFlags.NonPublic);
+ typeof(CompositionInvocation).GetField("target",
BindingFlags.Instance | BindingFlags.NonPublic);
public static readonly FieldInfo ProxyObject =
typeof(AbstractInvocation).GetField("proxyObject",
BindingFlags.Instance | BindingFlags.NonPublic);
@@ -48,25 +48,49 @@
public static readonly MethodInfo SetReturnValue =
typeof(AbstractInvocation).GetMethod("set_ReturnValue");
- public static readonly ConstructorInfo
ConstructorWithTargetMethod =
-
typeof(AbstractInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
- new[]
+ public static readonly ConstructorInfo
InheritanceInvocationConstructorNoSelector =
+
typeof(InheritanceInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
+
new[]
{
+
typeof(Type),
typeof(object),
+
typeof(IInterceptor[]),
+
typeof(MethodInfo),
+
typeof(object[])
+ },
+
null);
+
+ public static readonly ConstructorInfo
InheritanceInvocationConstructorWithSelector =
+
typeof(InheritanceInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
+
new[]
+ {
typeof(Type),
typeof(object),
typeof(IInterceptor[]),
typeof(MethodInfo),
+
typeof(object[]),
+
typeof(IInterceptorSelector),
+
typeof(IInterceptor[]).MakeByRefType()
+ },
+
null);
+
+ public static readonly ConstructorInfo
CompositionInvocationConstructorNoSelector =
+ typeof(CompositionInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
+
new[]
+ {
+
typeof(object),
+
typeof(object),
+
typeof(IInterceptor[]),
+
typeof(MethodInfo),
typeof(object[])
},
- null);
+
null);
- public static readonly ConstructorInfo
ConstructorWithTargetMethodWithSelector =
-
typeof(AbstractInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
- new[]
+ public static readonly ConstructorInfo
CompositionInvocationConstructorWithSelector =
+
typeof(CompositionInvocation).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null,
+
new[]
{
typeof(object),
-
typeof(Type),
typeof(object),
typeof(IInterceptor[]),
typeof(MethodInfo),
@@ -74,12 +98,12 @@
typeof(IInterceptorSelector),
typeof(IInterceptor[]).MakeByRefType()
},
- null);
+
null);
public static readonly MethodInfo Proceed =
typeof(AbstractInvocation).GetMethod("Proceed",
BindingFlags.Instance | BindingFlags.Public);
public static readonly MethodInfo EnsureValidTarget =
- typeof
(AbstractInvocation).GetMethod("EnsureValidTarget", BindingFlags.Instance |
BindingFlags.NonPublic);
+
typeof(CompositionInvocation).GetMethod("EnsureValidTarget",
BindingFlags.Instance | BindingFlags.NonPublic);
}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
=============================================================
File [modified]: InvocationMethodInvocationTargetTestCase.cs
Delta lines: +0 -0
===================================================================
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
====================================================================
File [modified]: ClassProxyTargetContributor.cs
Delta lines: +1 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyTargetContributor.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -79,7 +79,7 @@
invocationInterfaces = new[] {
typeof(IChangeProxyTarget) };
}
- var key = new CacheKey(method.Method,
invocationInterfaces, null);
+ var key = new CacheKey(method.Method,
InterfaceInvocationTypeGenerator.BaseType, invocationInterfaces, null);
// no locking required as we're already within a lock
File [modified]: InterfaceProxyTargetContributor.cs
Delta lines: +1 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -126,7 +126,7 @@
private Type GetInvocationType(MethodToGenerate method,
ClassEmitter emitter, ProxyGenerationOptions options)
{
var scope = emitter.ModuleScope;
- var key = new CacheKey(method.Method, null, null);
+ var key = new CacheKey(method.Method,
InterfaceInvocationTypeGenerator.BaseType, null, null);
// no locking required as we're already within a lock
File [modified]: InterfaceProxyWithoutTargetContributor.cs
Delta lines: +1 -1
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributor.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributor.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -148,7 +148,7 @@
{
interfaces = new[] { typeof(IChangeProxyTarget)
};
}
- var key = new CacheKey(method.Method, interfaces, null);
+ var key = new CacheKey(method.Method,
InterfaceInvocationTypeGenerator.BaseType, interfaces, null);
// no locking required as we're already within a lock
File [modified]: MixinContributor.cs
Delta lines: +16 -9
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/CacheKey.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/CacheKey.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -26,25 +26,32 @@
private readonly MemberInfo target;
private readonly Type[] interfaces;
private readonly ProxyGenerationOptions options;
- private readonly Type proxyForType;
+ private readonly Type type;
/// <summary>
/// Initializes a new instance of the <see cref="CacheKey"/>
class.
/// </summary>
- /// <param name="target">Type of the target.</param>
+ /// <param name="target">Target element. This is either target
type or target method for invocation types.</param>
+ /// <param name="type">The type of the proxy. This is base type
for invocation types.</param>
/// <param name="interfaces">The interfaces.</param>
/// <param name="options">The options.</param>
- public CacheKey(MemberInfo target, Type[] interfaces,
ProxyGenerationOptions options)
+ public CacheKey(MemberInfo target, Type type, Type[]
interfaces, ProxyGenerationOptions options)
{
this.target = target;
+ this.type = type;
this.interfaces = interfaces ?? Type.EmptyTypes;
this.options = options;
}
- public CacheKey(Type proxyForType, Type targetType, Type[]
interfaces, ProxyGenerationOptions options)
- : this(targetType, interfaces, options)
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheKey"/>
class.
+ /// </summary>
+ /// <param name="target">Type of the target.</param>
+ /// <param name="interfaces">The interfaces.</param>
+ /// <param name="options">The options.</param>
+ public CacheKey(Type target, Type[] interfaces,
ProxyGenerationOptions options)
+ : this(target, null, interfaces, options)
{
- this.proxyForType = proxyForType;
}
public override int GetHashCode()
@@ -56,8 +63,8 @@
}
if (options != null)
result = 29*result + options.GetHashCode();
- if (proxyForType != null)
- result = 29*result + proxyForType.GetHashCode();
+ if (type != null)
+ result = 29*result + type.GetHashCode();
return result;
}
@@ -68,7 +75,7 @@
CacheKey cacheKey = obj as CacheKey;
if (cacheKey == null) return false;
- if (!Equals(proxyForType, cacheKey.proxyForType))
return false;
+ if (!Equals(type, cacheKey.type)) return false;
if (!Equals(target, cacheKey.target)) return false;
if (interfaces.Length != cacheKey.interfaces.Length)
return false;
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenInterfaces/
===========================================================================
File [modified]: GenInterfaceWithGenericTypes.cs
Delta lines: +26 -3
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InvocationMethodInvocationTargetTestCase.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InvocationMethodInvocationTargetTestCase.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -14,28 +14,51 @@
namespace Castle.DynamicProxy.Tests
{
+ using System;
using System.Reflection;
using Castle.DynamicProxy.Tests.Classes;
using Castle.DynamicProxy.Tests.GenClasses;
using Castle.DynamicProxy.Tests.Interceptors;
using Castle.DynamicProxy.Tests.InterClasses;
+ using Castle.DynamicProxy.Tests.Interfaces;
+
using NUnit.Framework;
[TestFixture]
public class InvocationMethodInvocationTargetTestCase :
BasePEVerifyTestCase
{
[Test]
- public void
ClassProxy_MethodInvocationTarget_should_be_proxyMethod()
+ public void
ClassProxy_MethodInvocationTarget_should_be_base_Method()
{
var interceptor = new KeepDataInterceptor();
var proxy =
generator.CreateClassProxy<ServiceClass>(interceptor);
proxy.Sum(2, 2);
- MethodInfo methodOnProxy =
proxy.GetType().GetMethod("Sum", new[] { typeof(int), typeof(int) });
- Assert.AreSame(methodOnProxy,
interceptor.Invocation.MethodInvocationTarget);
+ var methodOnClass =
typeof(ServiceClass).GetMethod("Sum", new[] { typeof(int), typeof(int) });
+ Assert.AreSame(methodOnClass,
interceptor.Invocation.MethodInvocationTarget);
}
[Test]
+ public void
ClassProxy_MethodInvocationTarget_should_be_base_Method_for_interface_methods_implemented_non_virtually()
+ {
+ var interceptor = new KeepDataInterceptor();
+ var proxy = generator.CreateClassProxy(typeof(One),
new[] { typeof(IOne) }, interceptor) as IOne;
+ proxy.OneMethod();
+ var methodOnInterface =
typeof(One).GetMethod("OneMethod", Type.EmptyTypes);
+ Assert.AreSame(methodOnInterface,
interceptor.Invocation.MethodInvocationTarget);
+ }
+
+ [Test]
+ public void
ClassProxy_MethodInvocationTarget_should_be_base_Method_for_interface_methods_implemented_virtually()
+ {
+ var interceptor = new KeepDataInterceptor();
+ var proxy =
generator.CreateClassProxy(typeof(ClassWithVirtualInterface), new[] {
typeof(ISimpleInterface) }, interceptor) as ISimpleInterface;
+ proxy.Do();
+ var methodOnClass =
typeof(ClassWithVirtualInterface).GetMethod("Do", Type.EmptyTypes);
+ Assert.AreSame(methodOnClass,
interceptor.Invocation.MethodInvocationTarget);
+ }
+
+ [Test]
public void
InterfaceProxyWithTarget_MethodInvocationTarget_should_be_methodOnTargetType()
{
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
==================================================================
File [modified]: CacheKey.cs
Delta lines: +73 -0
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassInvocationTypeGenerator.cs
(rev 0)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassInvocationTypeGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -0,0 +1,73 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.DynamicProxy.Generators
+{
+ using System;
+ using System.Reflection;
+
+ using Castle.Core.Interceptor;
+ using Castle.DynamicProxy.Generators.Emitters;
+ using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
+ using Castle.DynamicProxy.Tokens;
+
+ public class ClassInvocationTypeGenerator : InvocationTypeGenerator
+ {
+ public ClassInvocationTypeGenerator(Type targetType,
IProxyMethod method, MethodInfo callback)
+ : base(targetType, method, callback, false)
+ {
+ }
+
+ protected override FieldReference GetTargetReference()
+ {
+ return new
FieldReference(InvocationMethods.ProxyObject);
+ }
+
+ protected override AbstractTypeEmitter GetEmitter(ClassEmitter
@class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo)
+ {
+ return new NestedClassEmitter(@class,
+
namingScope.GetUniqueName("Invocation_" + methodInfo.Name),
+
typeof(InheritanceInvocation),
+ interfaces);
+ }
+
+ protected override ArgumentReference[]
GetCtorArgumentsAndBaseCtorToCall(Type targetFieldType, ProxyGenerationOptions
proxyGenerationOptions, out ConstructorInfo baseConstructor)
+ {
+ if (proxyGenerationOptions.Selector == null)
+ {
+ baseConstructor =
InvocationMethods.InheritanceInvocationConstructorNoSelector;
+ return new[]
+ {
+ new ArgumentReference(typeof(Type)),
+ new ArgumentReference(typeof(object)),
+ new
ArgumentReference(typeof(IInterceptor[])),
+ new
ArgumentReference(typeof(MethodInfo)),
+ new ArgumentReference(typeof(object[]))
+ };
+ }
+
+ baseConstructor =
InvocationMethods.InheritanceInvocationConstructorWithSelector;
+ return new[]
+ {
+ new ArgumentReference(typeof(Type)),
+ new ArgumentReference(typeof(object)),
+ new ArgumentReference(typeof(IInterceptor[])),
+ new ArgumentReference(typeof(MethodInfo)),
+ new ArgumentReference(typeof(object[])),
+ new
ArgumentReference(typeof(IInterceptorSelector)),
+ new
ArgumentReference(typeof(IInterceptor[]).MakeByRefType())
+ };
+ }
+ }
+}
File [added]: ClassInvocationTypeGenerator.cs
Delta lines: +0 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -170,7 +170,6 @@
{
foreach (var mixinInterface in
ProxyGenerationOptions.MixinData.MixinInterfaces)
{
- object mixinInstance =
ProxyGenerationOptions.MixinData.GetMixinInstance(mixinInterface);
if
(targetInterfaces.Contains(mixinInterface))
{
File [modified]: ClassProxyGenerator.cs
Delta lines: +39 -3
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceInvocationTypeGenerator.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceInvocationTypeGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -16,32 +16,68 @@
{
using System;
using System.Reflection;
+
+ using Castle.Core.Interceptor;
+
using Emitters;
using Emitters.SimpleAST;
using Tokens;
public class InterfaceInvocationTypeGenerator : InvocationTypeGenerator
{
+ public static readonly Type BaseType =
typeof(CompositionInvocation);
+
public InterfaceInvocationTypeGenerator(Type target,
IProxyMethod method, MethodInfo callback, bool canChangeTarget)
: base(target, method, callback, canChangeTarget)
{
}
+ protected override FieldReference GetTargetReference()
+ {
+ return new FieldReference(InvocationMethods.Target);
+ }
+
protected override AbstractTypeEmitter GetEmitter(ClassEmitter
@class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo)
{
var suggestedName =
string.Format("Castle.Proxies.Invocations.{0}_{1}",
methodInfo.DeclaringType.Name,
methodInfo.Name);
var uniqueName =
namingScope.ParentScope.GetUniqueName(suggestedName);
- return new ClassEmitter(@class.ModuleScope, uniqueName,
typeof(AbstractInvocation), interfaces);
+ return new ClassEmitter(@class.ModuleScope, uniqueName,
BaseType, interfaces);
}
- protected override void
ImplementInvokeMethodOnTarget(AbstractTypeEmitter nested, ParameterInfo[]
parameters, MethodEmitter method, MethodInfo callbackMethod, Reference
targetField)
+ protected override void
ImplementInvokeMethodOnTarget(AbstractTypeEmitter @class, ParameterInfo[]
parameters, MethodEmitter method, MethodInfo callbackMethod, Reference
targetField)
{
method.CodeBuilder.AddStatement(
new ExpressionStatement(
new
MethodInvocationExpression(SelfReference.Self,
InvocationMethods.EnsureValidTarget)));
- base.ImplementInvokeMethodOnTarget(nested, parameters,
method, callbackMethod, targetField);
+ base.ImplementInvokeMethodOnTarget(@class, parameters,
method, callbackMethod, targetField);
}
+ protected override ArgumentReference[]
GetCtorArgumentsAndBaseCtorToCall(Type targetFieldType, ProxyGenerationOptions
proxyGenerationOptions,out ConstructorInfo baseConstructor)
+ {
+ if (proxyGenerationOptions.Selector == null)
+ {
+ baseConstructor =
InvocationMethods.CompositionInvocationConstructorNoSelector;
+ return new[]
+ {
+ new ArgumentReference(targetFieldType),
+ new ArgumentReference(typeof(object)),
+ new
ArgumentReference(typeof(IInterceptor[])),
+ new
ArgumentReference(typeof(MethodInfo)),
+ new ArgumentReference(typeof(object[])),
+ };
+ }
+ baseConstructor =
InvocationMethods.CompositionInvocationConstructorWithSelector;
+ return new[]
+ {
+ new ArgumentReference(targetFieldType),
+ new ArgumentReference(typeof(object)),
+ new ArgumentReference(typeof(IInterceptor[])),
+ new ArgumentReference(typeof(MethodInfo)),
+ new ArgumentReference(typeof(object[])),
+ new
ArgumentReference(typeof(IInterceptorSelector)),
+ new
ArgumentReference(typeof(IInterceptor[]).MakeByRefType())
+ };
+ }
}
}
File [modified]: InterfaceInvocationTypeGenerator.cs
Delta lines: +0 -2
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceMethodGenerator.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceMethodGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -90,7 +90,6 @@
ctorArguments = new[]
{
getTargetExpression(@class, methodInfo),
- new
TypeTokenExpression(Method.MethodOnTarget.DeclaringType),
SelfReference.Self.ToExpression(),
interceptors.ToExpression(),
interfaceMethod,
@@ -102,7 +101,6 @@
ctorArguments = new[]
{
getTargetExpression(@class, methodInfo),
- new
TypeTokenExpression(Method.MethodOnTarget.DeclaringType),
SelfReference.Self.ToExpression(),
interceptors.ToExpression(),
File [modified]: InterfaceMethodGenerator.cs
Delta lines: +25 -52
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -22,14 +22,14 @@
using Emitters.SimpleAST;
using Tokens;
- public class InvocationTypeGenerator : IGenerator<AbstractTypeEmitter>
+ public abstract class InvocationTypeGenerator :
IGenerator<AbstractTypeEmitter>
{
private readonly Type targetType;
private readonly IProxyMethod method;
private readonly MethodInfo callback;
private readonly bool canChangeTarget;
- public InvocationTypeGenerator(Type targetType, IProxyMethod
method, MethodInfo callback, bool canChangeTarget)
+ protected InvocationTypeGenerator(Type targetType, IProxyMethod
method, MethodInfo callback, bool canChangeTarget)
{
this.targetType = targetType;
this.method = method;
@@ -41,7 +41,7 @@
{
var methodInfo = method.Method;
- Type[] interfaces = new Type[0];
+ var interfaces = new Type[0];
if (canChangeTarget)
{
@@ -56,9 +56,14 @@
// Create constructor
- CreateIInvocationConstructor(targetType, type,options);
+ ConstructorInfo baseConstructor;
+ var arguments =
GetCtorArgumentsAndBaseCtorToCall(targetType,options, out baseConstructor);
- var targetField = new
FieldReference(InvocationMethods.Target);
+ var constructor = type.CreateConstructor(arguments);
+
constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, arguments);
+ constructor.CodeBuilder.AddStatement(new
ReturnStatement());
+
+ var targetField = GetTargetReference();
if (canChangeTarget)
{
ImplementChangeProxyTargetInterface(@class,
type, targetField);
@@ -86,14 +91,11 @@
return type;
}
- protected virtual AbstractTypeEmitter GetEmitter(ClassEmitter
@class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo)
- {
- return new NestedClassEmitter(@class,
-
namingScope.GetUniqueName("Invocation_" + methodInfo.Name),
-
typeof(AbstractInvocation),
-
interfaces);
- }
+ protected abstract FieldReference GetTargetReference();
+ protected abstract AbstractTypeEmitter GetEmitter(ClassEmitter
@class, Type[] interfaces, INamingScope namingScope,
+ MethodInfo
methodInfo);
+
private void ImplementChangeProxyTargetInterface(ClassEmitter
@class, AbstractTypeEmitter invocation, FieldReference targetField)
{
ImplementChangeInvocationTarget(invocation,
targetField);
@@ -134,16 +136,16 @@
changeInvocationTarget.CodeBuilder.AddStatement(new
ReturnStatement());
}
- protected void
CreateIInvocationInvokeOnTarget(AbstractTypeEmitter nested, ParameterInfo[]
parameters, FieldReference targetField, MethodInfo callbackMethod)
+ private void
CreateIInvocationInvokeOnTarget(AbstractTypeEmitter @class, ParameterInfo[]
parameters, FieldReference targetField, MethodInfo callbackMethod)
{
const MethodAttributes methodAtts =
MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual;
- MethodEmitter method =
nested.CreateMethod("InvokeMethodOnTarget", methodAtts, typeof(void));
+ MethodEmitter method =
@class.CreateMethod("InvokeMethodOnTarget", methodAtts, typeof(void));
- ImplementInvokeMethodOnTarget(nested, parameters,
method, callbackMethod, targetField);
+ ImplementInvokeMethodOnTarget(@class, parameters,
method, callbackMethod, targetField);
}
- protected virtual void
ImplementInvokeMethodOnTarget(AbstractTypeEmitter nested, ParameterInfo[]
parameters, MethodEmitter method, MethodInfo callbackMethod, Reference
targetField)
+ protected virtual void
ImplementInvokeMethodOnTarget(AbstractTypeEmitter @class, ParameterInfo[]
parameters, MethodEmitter method, MethodInfo callbackMethod, Reference
targetField)
{
if (canChangeTarget)
@@ -163,7 +165,7 @@
{
ParameterInfo param = parameters[i];
- Type paramType =
TypeUtil.GetClosedParameterType(nested, param.ParameterType);
+ Type paramType =
TypeUtil.GetClosedParameterType(@class, param.ParameterType);
if (paramType.IsByRef)
{
LocalReference localReference =
method.CodeBuilder.DeclareLocal(paramType.GetElementType());
@@ -189,7 +191,7 @@
if (callbackMethod.IsGenericMethod)
{
- callbackMethod =
callbackMethod.MakeGenericMethod(nested.GetGenericArgumentsFor(callbackMethod));
+ callbackMethod =
callbackMethod.MakeGenericMethod(@class.GetGenericArgumentsFor(callbackMethod));
}
var methodOnTargetInvocationExpression = new
MethodInvocationExpression(
@@ -200,7 +202,7 @@
LocalReference returnValue = null;
if (callbackMethod.ReturnType != typeof(void))
{
- Type returnType =
TypeUtil.GetClosedParameterType(nested, callbackMethod.ReturnType);
+ Type returnType =
TypeUtil.GetClosedParameterType(@class, callbackMethod.ReturnType);
returnValue =
method.CodeBuilder.DeclareLocal(returnType);
method.CodeBuilder.AddStatement(new
AssignStatement(returnValue, methodOnTargetInvocationExpression));
}
@@ -256,42 +258,13 @@
}
/// <summary>
- /// Generates the constructor for the nested class that extends
+ /// Generates the constructor for the class that extends
/// <see cref="AbstractInvocation"/>
/// </summary>
/// <param name="targetFieldType"></param>
- /// <param name="nested"></param>
/// <param name="proxyGenerationOptions"></param>
- protected void CreateIInvocationConstructor(Type
targetFieldType, AbstractTypeEmitter nested, ProxyGenerationOptions
proxyGenerationOptions)
- {
- var target = new ArgumentReference(targetFieldType);
- var targetType = new ArgumentReference(typeof(Type));
- var proxy = new ArgumentReference(typeof(object));
- var interceptors = new
ArgumentReference(typeof(IInterceptor[]));
- var proxiedMethod = new
ArgumentReference(typeof(MethodInfo));
- var arguments = new ArgumentReference(typeof(object[]));
-
- ConstructorEmitter constructor;
- if (proxyGenerationOptions.Selector != null)
- {
- var selector = new
ArgumentReference(typeof(IInterceptorSelector));
- var methodInterceptorsByRef = new
ArgumentReference(typeof(IInterceptor[]).MakeByRefType());
- constructor = nested.CreateConstructor(target,
targetType, proxy, interceptors, proxiedMethod, arguments,
-
selector, methodInterceptorsByRef);
-
- constructor.CodeBuilder.InvokeBaseConstructor(
-
InvocationMethods.ConstructorWithTargetMethodWithSelector,
- target, targetType, proxy,
interceptors, proxiedMethod, arguments, selector, methodInterceptorsByRef);
- }
- else
- {
- constructor = nested.CreateConstructor(target,
targetType, proxy, interceptors, proxiedMethod, arguments);
-
- constructor.CodeBuilder.InvokeBaseConstructor(
-
InvocationMethods.ConstructorWithTargetMethod,
- target, targetType, proxy,
interceptors, proxiedMethod, arguments);
- }
- constructor.CodeBuilder.AddStatement(new
ReturnStatement());
- }
+ /// <param name="baseConstructor"></param>
+ protected abstract ArgumentReference[]
GetCtorArgumentsAndBaseCtorToCall(Type targetFieldType, ProxyGenerationOptions
proxyGenerationOptions, out ConstructorInfo baseConstructor);
+
}
}
File [modified]: InvocationTypeGenerator.cs
Delta lines: +4 -5
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/MethodWithCallbackGenerator.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/MethodWithCallbackGenerator.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -28,13 +28,15 @@
public class MethodWithCallbackGenerator:MethodGenerator
{
+ private readonly Type targetType;
private readonly MethodToGenerate method;
private readonly AbstractTypeEmitter invocation;
private readonly Reference interceptors;
private readonly CreateMethodDelegate createMethod;
- public MethodWithCallbackGenerator(MethodToGenerate method,
AbstractTypeEmitter invocation, Reference interceptors, CreateMethodDelegate
createMethod)
+ public MethodWithCallbackGenerator(Type targetType,
MethodToGenerate method, AbstractTypeEmitter invocation, Reference
interceptors, CreateMethodDelegate createMethod)
{
+ this.targetType = targetType;
this.method = method;
this.invocation = invocation;
this.interceptors = interceptors;
@@ -85,6 +87,7 @@
MethodInfo genericMethod =
methodInfo.MakeGenericMethod(genericMethodArgs);
proxiedMethodTokenExpression = new
MethodTokenExpression(genericMethod);
+
}
else
{
@@ -104,8 +107,6 @@
constructor =
TypeBuilder.GetConstructor(iinvocation, constructor);
}
- // TODO: this is not always true. Should be passed
explicitly as ctor parameter
- Type targetType = methodInfo.DeclaringType;
Debug.Assert(targetType != null, "targetType != null");
Expression[] ctorArgs;
@@ -114,7 +115,6 @@
{
ctorArgs = new[]
{
- SelfReference.Self.ToExpression(),
new TypeTokenExpression(targetType),
SelfReference.Self.ToExpression(),
interceptors.ToExpression(),
@@ -126,7 +126,6 @@
{
ctorArgs = new[]
{
- SelfReference.Self.ToExpression(),
new TypeTokenExpression(targetType),
SelfReference.Self.ToExpression(),
File [modified]: MethodWithCallbackGenerator.cs
Delta lines: +67 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/InheritanceInvocation.cs
(rev 0)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/InheritanceInvocation.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -0,0 +1,67 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.DynamicProxy
+{
+ using System;
+ using System.Reflection;
+
+ using Castle.Core.Interceptor;
+
+ public abstract class InheritanceInvocation : AbstractInvocation
+ {
+ public override object InvocationTarget
+ {
+ get { return Proxy; }
+ }
+
+ private readonly Type targetType;
+
+ protected InheritanceInvocation(
+ Type targetType,
+ object proxy,
+ IInterceptor[] interceptors,
+ MethodInfo proxiedMethod,
+ object[] arguments)
+ : base(proxy, interceptors, proxiedMethod, arguments)
+ {
+ this.targetType = targetType;
+ }
+
+ protected InheritanceInvocation(
+ Type targetType,
+ object proxy,
+ IInterceptor[] interceptors,
+ MethodInfo proxiedMethod,
+ object[] arguments,
+ IInterceptorSelector selector,
+ ref IInterceptor[] methodInterceptors)
+ : base(proxy, targetType, interceptors, proxiedMethod,
arguments, selector, ref methodInterceptors)
+ {
+ this.targetType = targetType;
+ }
+
+ public override Type TargetType
+ {
+ get { return targetType; }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { return
InvocationHelper.GetMethodOnType(targetType, Method); }
+ }
+
+ protected abstract override void InvokeMethodOnTarget();
+ }
+}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
==============================================================
File [modified]: InvocationMethods.cs
Delta lines: +71 -5
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenInterfaces/GenInterfaceWithGenericTypes.cs
2009-11-26 21:11:25 UTC (rev 6363)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenInterfaces/GenInterfaceWithGenericTypes.cs
2009-11-26 22:41:19 UTC (rev 6364)
@@ -110,14 +110,30 @@
public class Find2Invo<T> : AbstractInvocation
{
+ private GenInterfaceWithGenericTypesImpl target;
public Find2Invo(GenInterfaceWithGenericTypesImpl
target, IInterceptor[] interceptors, Type targetType,
MethodInfo targetMethod, MethodInfo
interfMethod, object[] arguments)
- : base(target,targetType, target, interceptors,
interfMethod, arguments)
+ : base(target, interceptors, interfMethod,
arguments)
{
this.target = target;
}
+ public override object InvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override Type TargetType
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
protected override void InvokeMethodOnTarget()
{
ReturnValue = (target as
GenInterfaceWithGenericTypesImpl).Find<T>((String) GetArgumentValue(0));
@@ -126,14 +142,30 @@
public class Find1Invo : AbstractInvocation
{
+ private GenInterfaceWithGenericTypesImpl target;
public Find1Invo(GenInterfaceWithGenericTypesImpl
target, IInterceptor[] interceptors, Type targetType,
MethodInfo targetMethod, MethodInfo
interfMethod, object[] arguments) :
- base(target, targetType, target, interceptors,
interfMethod, arguments)
+ base(target, interceptors, interfMethod,
arguments)
{
this.target = target;
}
+ public override object InvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override Type TargetType
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
protected override void InvokeMethodOnTarget()
{
ReturnValue = (target as
GenInterfaceWithGenericTypesImpl).Find((String[,]) GetArgumentValue(0));
@@ -142,14 +174,30 @@
public class Find1InvoA : AbstractInvocation
{
+ private GenInterfaceWithGenericTypesImpl target;
+
public Find1InvoA(GenInterfaceWithGenericTypesImpl
target, IInterceptor[] interceptors, Type targetType,
MethodInfo targetMethod, MethodInfo
interfMethod, object[] arguments)
- :
- base(target, targetType, target,
interceptors, interfMethod, arguments)
+ :base(target, interceptors, interfMethod,
arguments)
{
this.target = target;
}
+ public override object InvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override Type TargetType
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
protected override void InvokeMethodOnTarget()
{
ReturnValue = (target as
GenInterfaceWithGenericTypesImpl).Find((String) GetArgumentValue(0));
@@ -158,13 +206,31 @@
public class Find3Invo<T> : AbstractInvocation
{
+ private GenInterfaceWithGenericTypesImpl target;
+
public Find3Invo(GenInterfaceWithGenericTypesImpl
target,
IInterceptor[] interceptors, Type
targetType,
MethodInfo targetMethod, MethodInfo
interfMethod, object[] arguments)
- : base(target, targetType, target,
interceptors, interfMethod, arguments)
+ : base(target, interceptors, interfMethod,
arguments)
{
+ this.target = target;
}
+ public override object InvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override Type TargetType
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override MethodInfo MethodInvocationTarget
+ {
+ get { throw new NotImplementedException(); }
+ }
+
protected override void InvokeMethodOnTarget()
{
--
You received this message because you are subscribed to the Google Groups
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-commits?hl=en.