Kam,
You ask for a proxy with target interface. That's the crucial part here.
This kind of proxy takes no assumption about what the type of the target
object is.
You then ask it to create a proxy, where IInterfaceB is the main target,
and ICommon is additional interfaces. That means that the target is
required to implement InterfaceB, and it might or might not implement
InterfaceA or ICommon.
Hence when you ask NOT to proxy TestB, since InterfaceB is the primary
interface for proxy the call will be forwarded to the target object.
In Castle of Common2, target does not need to implement it, so when you
ask NOT to proxy the method, DP does not proxy it, nor does it try to
forward the call to target, since it takes no assumptions about the target.
To get the behavior you want use interface proxy with target.
However I agree that the behavior you were expecting makes some sense in
case of proxy with target interface as well, so if you want, go ahead
and log it in the issue tracker as future enhancement.
cheers,
Krzysztof
On 25/09/2010 11:49 PM, Kam wrote:
Sorry about that. Here's the amalgamated code listing.
Kam
----------------
using System;
using System.Reflection;
using Castle.DynamicProxy;
namespace GenericMethodProxyTest
{
class Program
{
static void Main(string[] args)
{
var tb = new TestB();
Type[] interfaces = tb.GetType().GetInterfaces();
var proxyGenerator = new ProxyGenerator();
var genOptions = new ProxyGenerationOptions { Hook = new
NonProxiedGenerationHook() };
var proxy =
(IInterfaceB)proxyGenerator.CreateInterfaceProxyWithTargetInterface(typeof(IInterfaceB),
interfaces,
tb, genOptions, new ActiveObjectInterceptor());
((IInterfaceA)proxy).TestA1();
((IInterfaceA)proxy).TestA2();
((IInterfaceB)proxy).TestB1();
((IInterfaceB)proxy).TestB2();
((ICommon)proxy).Common1();
// Stepping in will not go anywhere. The target method is never
reached since there's no console output.
((ICommon)proxy).Common2();
}
}
public class NonProxiedAttribute : Attribute
{
}
public interface ICommon
{
void Common1();
[NonProxied] // This one doesn't work, it doesn't seem to do
anything for the call.
void Common2();
}
public interface IInterfaceA
{
void TestA1();
void TestA2();
}
public interface IInterfaceB
{
void TestB1();
[NonProxied] // This one works, the call to TestB2 is not
intercepted but reaches target.
void TestB2();
}
public abstract class TestA : IInterfaceA, ICommon
{
void ICommon.Common1()
{
Console.WriteLine(" - Reached target Common1()\n");
}
void ICommon.Common2()
{
Console.WriteLine(" - Reached target Common2()\n");
}
void IInterfaceA.TestA1()
{
Console.WriteLine(" - Reached target TestA1()\n");
}
void IInterfaceA.TestA2()
{
Console.WriteLine(" - Reached target TestA2()\n");
}
}
public class TestB : TestA, IInterfaceB
{
void IInterfaceB.TestB1()
{
Console.WriteLine(" - Reached target TestB1()\n");
}
void IInterfaceB.TestB2()
{
Console.WriteLine(" - Reached target TestB2()\n");
}
}
public class ActiveObjectInterceptor : StandardInterceptor
{
protected override void PerformProceed(IInvocation invocation)
{
Console.WriteLine(String.Format("Intercepted call to {0}\n",
invocation.Method.Name));
base.PerformProceed(invocation);
}
}
public abstract class ProxyGenerationHookBase : IProxyGenerationHook
{
public abstract bool ShouldInterceptMethod(Type type, MethodInfo
methodInfo);
public virtual void NonProxyableMemberNotification(Type type,
MemberInfo memberInfo)
{
}
public virtual void MethodsInspected()
{
}
protected bool IsPropertyAccessor(MethodInfo method)
{
return (IsPropertySetter(method) | IsPropertyGetter(method));
}
protected bool IsPropertySetter(MethodInfo method)
{
var methodName = method.Name;
return (method.IsSpecialName&& methodName.StartsWith("set_",
StringComparison.Ordinal));
}
protected bool IsPropertyGetter(MethodInfo method)
{
var methodName = method.Name;
return (method.IsSpecialName&& methodName.StartsWith("get_",
StringComparison.Ordinal));
}
}
public class NonProxiedGenerationHook : ProxyGenerationHookBase
{
public override bool ShouldInterceptMethod(Type type, MethodInfo
methodInfo)
{
bool intercept = true;
if (methodInfo.IsDefined(typeof(NonProxiedAttribute), true))
{
intercept = false;
}
return intercept;
}
#region Equality
public override bool Equals(object obj)
{
return ((obj != null)&& (obj.GetType() ==
typeof(NonProxiedGenerationHook)));
}
public override int GetHashCode()
{
return GetType().GetHashCode();
}
public static bool operator ==(NonProxiedGenerationHook left,
NonProxiedGenerationHook right)
{
return Equals(left, right);
}
public static bool operator !=(NonProxiedGenerationHook left,
NonProxiedGenerationHook right)
{
return !Equals(left, right);
}
#endregion
}
}
On Sep 25, 3:00 am, Krzysztof Koźmic<[email protected]>
wrote:
Can you provide full code that compiles and runs?
cheers,
Krzysztof
On 24/09/2010 11:53 AM, Kam wrote:
Hi Krzysztof, thanks for lending a hand. Here's a quick snippet of the
failing test along with console output.
*************
class Program
{
static void Main(string[] args)
{
var tb = new TestB();
Type[] interfaces = tb.GetType().GetInterfaces();
var factory = new ProxyFactory();
var proxy =
factory.CreateInterfaceProxyWithTarget<IInterfaceB>(tb, new[]
{ InterceptorType.Validator },
ProxyGenerationHookType.Selective, interfaces);
((IInterfaceA)proxy).TestA1();
((IInterfaceA)proxy).TestA2();
((IInterfaceB)proxy).TestB1();
((IInterfaceB)proxy).TestB2();
((ICommon)proxy).Common1();
// Stepping in will not go anywhere. The target method is never
reached since there's no console output.
((ICommon)proxy).Common2();
}
}
public interface ICommon
{
void Common1();
[NonProxied] // This one doesn't work, it doesn't seem to do
anything for the call.
void Common2();
}
public interface IInterfaceA
{
void TestA1();
void TestA2();
}
public interface IInterfaceB
{
void TestB1();
[NonProxied] // This one works, the call to TestB2 is not
intercepted but reaches target.
void TestB2();
}
public abstract class TestA : IInterfaceA, ICommon
{
void ICommon.Common1()
{
Console.WriteLine(" - Reached target Common1()\n");
}
void ICommon.Common2()
{
Console.WriteLine(" - Reached target Common2()\n");
}
void IInterfaceA.TestA1()
{
Console.WriteLine(" - Reached target TestA1()\n");
}
void IInterfaceA.TestA2()
{
Console.WriteLine(" - Reached target TestA2()\n");
}
}
public class TestB : TestA, IInterfaceB
{
void IInterfaceB.TestB1()
{
Console.WriteLine(" - Reached target TestB1()\n");
}
void IInterfaceB.TestB2()
{
Console.WriteLine(" - Reached target TestB2()\n");
}
}
public class ActiveObjectInterceptor : StandardInterceptor
{
protected override void PerformProceed(IInvocation invocation)
{
Console.WriteLine(String.Format("Intercepted call to {0}\n",
invocation.Method.Name));
base.PerformProceed(invocation);
}
}
public class NonProxiedGenerationHook : ProxyGenerationHookBase
{
public override bool ShouldInterceptMethod(Type type, MethodInfo
methodInfo)
{
bool intercept = true;
if (methodInfo.IsDefined(typeof(NonProxiedAttribute), true))
{
intercept = false;
}
return intercept;
}
#region Equality
...
#endregion
}
***************
Output:
Intercepted call to TestA1
- Reached target TestA1()
Intercepted call to TestA2
- Reached target TestA2()
Intercepted call to TestB1
- Reached target TestB1()
- Reached target TestB2()
Intercepted call to Common1
- Reached target Common1()
*********************
As you can see, I expected to see the line "- Reached target
Common2()" without the line "Intercepted call to Common2()" much like
the non-proxied call to TestB2(). I made sure the supplied list of
additional interfaces to proxy does include ICommon.
Thanks
On Sep 23, 8:19 pm, Krzysztof Koźmic<[email protected]>
wrote:
can you provide a failing test?
I'm not sure I understand the scenario 2 here
2010/9/24 Kam<[email protected]>
Hi,
I'm currently using IProxyGenerationHook to control which methods to
exclude for proxy generation for a given interface. My current
hierarchy of classes and interfaces is the following:
Class_A implements interfaces Interface_A and Interface_Z
Class_B inherits Class_A and also implements interfaces Interface_B
Interface_B inherits Interface_Z.
I created a proxy to interface Interface_B with a target instance of
Class_B, and gave it Interface_Z as additional interface to include in
the proxy generation process.
I use custom attributes on methods/properties to mark for exclusion.
i.e. [NonProxied].
Scenario 1:
If I mark a method belonging to Interface_B, the hook will exclude it
and any calls through the proxy to that marked method will reach the
target object's method without interception. (Behaviour I expected).
Scenario 2:
If I mark a method belonging to Interface_Z and cast my proxy instance
to (Interface_Z) to make a call to the marked method, the call will
not reach its target object. From a debugger point of view, attempting
to step-in won't do anything. The execution proceeds to the next line
without interception nor forwarding to the real implementation. I get
this behaviour even without attaching the debugger. (Expected the call
to reach the target instance's method implementation without
interceptors).
To summarize, using proxy generation hook to exclude seems to work
only for first level interface methods and properties but not for
inherited interfaces with marked methods or properties.
Perhaps this is not supported or I'm just missing something? Has
anyone else experienced a similar scenario?
Thanks in advance!
--
You received this message because you are subscribed to the Google Groups
"Castle Project Users" group.
To post to this group, send email to [email protected]
.
To unsubscribe from this group, send email to
[email protected]<castle-project-users%[email protected]>
.
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google Groups "Castle
Project Users" 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-users?hl=en.