Hi All I'm trying to use DynamicProxy to create a proxy object for a remote interface. For that to work I've done the following. I have defined a base interface for all command interfaces. This base interface doesn't provide any command methods but does provide an event. The base interface looks like this:
public interface ICommands
{
event EventHandler<EventArgs> OnTerminated;
}
That base interface is implemented by a proxy base class which will be used
to refer to the proxy in the storage layer. The definition of that base
proxy object looks like:
public class CommandProxy : ICommands
{
public event EventHandler<EventArgs> OnTerminated;
private void RaiseOnAvailabilityChange()
{
var local = OnTerminated;
if (local != null)
{
local(SelfReference(), EventArgs.Empty);
}
}
// Stop the leaking of the 'this' reference by getting it from this
method
// The proxy will override this method and make sure we only return
the
// link to the proxy.
protected internal virtual object SelfReference()
{
return this;
}
}
Interfaces that derive from ICommands are only allowed to have methods that
either return Task or Task<T> to indicate that any method called on the
interface is likely to take up a finite amount of time. An example
definition of a command interface looks like this:
public interface ICoolCommands : ICommands
{
Task SomeMethod(int input);
Task<int> SomeOtherMethod(int input);
}
The actual definition of the command interfaces may be different and is not
known to the proxy building code.
I've then defined several interceptors to handle the case of methods with a
Task return value and methods with a Task<T> return value.
The first interceptor handles (I think) the 'SelfRefence' method in the base
proxy object.
internal sealed class CommandSetProxySelfReferenceInterceptor :
IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue = invocation.Proxy;
}
}
The following two interceptors handle the case of methods with a Task and a
Task<T> return value. Note that these interceptors never call in to the
proxy base object because that object doesn't have any of the correct
methods implemented.
internal sealed class CommandSetMethodWithTaskResultInterceptor :
IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue =
Task.Factory.StartNew(
() => Console.WriteLine(
string.Format("{}({})",
invocation.Method.Name,
invocation.Arguments[0])));
}
}
internal sealed class CommandSetMethodWithTypedTaskResultInterceptor :
IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue =
Task<int>.Factory.StartNew(
() =>
{
Console.WriteLine(
string.Format("{}({})",
invocation.Method.Name,
invocation.Arguments[0]));
return 10;
});
}
}
And finally there is an interceptorselector to handle setting up the
interceptor chains.
internal sealed class CommandSetInterceptorSelector :
IInterceptorSelector
{
public IInterceptor[] SelectInterceptors(Type type, MethodInfo
method, IInterceptor[] interceptors)
{
var name = "SelfReference";
if (string.Equals(name, method.Name, StringComparison.Ordinal))
{
return interceptors.Where(i => i is
CommandSetProxySelfReferenceInterceptor).ToArray();
}
if (method.ReturnType == typeof(Task))
{
return interceptors.Where(i => i is
CommandSetMethodWithTaskResultInterceptor).ToArray();
}
return interceptors.Where(i => i is
CommandSetMethodWithTypedTaskResultInterceptor).ToArray();
}
}
Now to build the proxy I use the following code (simplified from the real
code)
class Program
{
static void Main(string[] args)
{
var baseObject = new CommandProxy();
var selfReference = new
CommandSetProxySelfReferenceInterceptor();
var methodWithoutResult = new
CommandSetMethodWithTaskResultInterceptor();
var methodWithResult = new
CommandSetMethodWithTypedTaskResultInterceptor();
var options = new ProxyGenerationOptions
{
Selector = new CommandSetInterceptorSelector(),
};
var generator = new ProxyGenerator();
var proxy =
(ICoolCommands)generator.CreateInterfaceProxyWithTarget(
typeof(ICoolCommands),
baseObject,
options,
new IInterceptor[] { selfReference, methodWithoutResult,
methodWithResult });
proxy.SomeMethod(10);
var result = proxy.SomeOtherMethod(20);
Console.ReadLine();
}
}
The problem is that it fails when I try to create the proxy (the line that
has generator.CreateInterfaceProxyWithTarget) because the target doesn't
implement the ICoolCommands interface. So the question now is how can I:
- Create a proxy for a derivative of the ICommands interface, without the
proxy code knowing what that interface is going to be
- Have a base object that I can use to invoke events on
I suspect I want some form of mixin (as shown here
http://kozmic.pl/2009/08/12/castle-dynamic-proxy-tutorial-part-xiii-mix-in-this-mix)
but I'm not sure about that. If anybody has any good suggestions then that
would be awesome.
In case it's necessary I've attached a C# code file with the example code.
With kind regards
Patrick van der Velde
--
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.
Program.cs
Description: Binary data
