60

I want to build a dynamic proxy object to add certain functionality to an object.

basically i want to receive an object, wrap it with an object that looks identical to the original i got, and intercept all the calls.

class Wrapper : DynamicProxy// dynamic proxy is not a reall class, but i guess something like this exists... { public static T Wrap(T obj) { return (T) new Wrapper(obj); } public override object InterceptCall(MethodInfo info, object[] args) { // do stuff } } 

Just to clarify, I want to do something similar to the WCF channel factory...


I'm adding a bounty, because I need a good way to proxy classes (not interfaces) and to handle non virtual methods (as if I inherited and added a methond under the "new" keyword). I'm sure all this is very possible as the .Net does it.

8
  • 5
    have you looked at castleproject.org/dynamicproxy/index.html ? Commented Dec 5, 2011 at 14:44
  • @np-hard if you post this as an answer, i will accept it... not 100% what i was looking for, but good enough. Commented Dec 21, 2011 at 19:25
  • Do you know the type you want to proxy at compile time, or only at runtime? Commented Jan 3, 2012 at 16:04
  • @Sneal only at run time. probably I'll know it at compile time but i want to keep flexibility... Commented Jan 3, 2012 at 16:10
  • That definitely makes things a lot harder, as Castle DynamicProxy can only intercept virtual methods. I think you're stuck using the profiling api. Commented Jan 3, 2012 at 16:18

9 Answers 9

47

You could do this with a combination of DynamicObject and ImpromptuInterface but you will have to have an Interface that implements the functions and properties you want to proxy.

public interface IDoStuff { void Foo(); } public class Wrapper<T> : DynamicObject { private readonly T _wrappedObject; public static T1 Wrap<T1>(T obj) where T1 : class { if (!typeof(T1).IsInterface) throw new ArgumentException("T1 must be an Interface"); return new Wrapper<T>(obj).ActLike<T1>(); } //you can make the contructor private so you are forced to use the Wrap method. private Wrapper(T obj) { _wrappedObject = obj; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { try { //do stuff here //call _wrappedObject object result = _wrappedObject.GetType().GetMethod(binder.Name).Invoke(_wrappedObject, args); return true; } catch { result = null; return false; } } } 

You could of course choose to lose the type-safety and go with a DynamicObject like I showed and then drop the duck-casting.

I made a transparant extendible version of this object proxy, and open-sourced it here.

Sign up to request clarification or add additional context in comments.

5 Comments

Could you say just a word about how ImpromptuInterface works under the hood? That is, what technique does ActLike use to create an object of any type? Some kind of byte code generation?
@Lii I didn't develop ImpromptuInterface. But it uses the DLR to dynamically bind to functions on the ducktyped object. And then it uses that same trick to cast it to the Interface you specify.
What's the performance impact of something like this? AFAIK .GetType() is not very performance friendly.
Yeah it's prolly a smart idea to examine the type on construction and drop all the functions in a dict. Ehhh I went for simplicity in my explanation not performance.
@FrankerZ if you look at the my project here: github.com/curit/DynamicProxy/blob/master/DynamicProxy/… you'll see I did it differently there. :)
17

In addition to Castle.DynamicProxy, there is also LinFu.DynamicProxy on Github.

Comments

16

I should have written this sooner, but never mind.

My issue had a special "gotcha" I needed to be able to proxy classes and not interfaces.

There are two solutions to this:

  1. RealProxy and friends, basically means using .NET Remoting. Requires one to inherit from ContextBoundObject.

  2. Building a proxy using System.Reflection.Emit as done by spring you can also look at the code of their ProxyFactoryObject. Here are another three articles on the subject.

    • This approach has the crucial disadvantage of limiting you to overriding only virtual members.

1 Comment

No. But you can follow the links and find far better examples and explenations than anything I can write here.
9

.NET 6.0 has added a new candidate to the Reflection namespace: the DispatchProxy. The team is announcing it here. A sample usage is contained in the article.

Comments

5

Take a look at PostSharp. I don't know of a way to do what you want in vanilla .Net, but PostSharp offers things like "OnMethodBoundaryAspect" which can be used to either replace or wrap the code inside the method.

I've used it to do things like logging, parameter validation, exception handling etc.

There is a free Community Edition, which should work for you. You'll need it installed on your development machine, as well as any build server that you use.

1 Comment

Postsharp works at compile time for known types. I don't think is what OP needed
3

Another option is ContextBoundObject.

There was an article on CodeProject about 8-9 years back using this approach to trace method calls.

Comments

1

You could do this with just DynamicObject from System.Danymic namespace, without using any third party libraries.

Example code:

public class DynamicProxy: DynamicObject { private readonly T _object; // The inner dictionary. Dictionary<string, object> dictionary = new Dictionary<string, object>(); // Getting a property. public override bool TryGetMember(GetMemberBinder binder, out object result) { return dictionary.TryGetValue(binder.Name, out result); } // Setting a property. // You can set up access control eg. if you don't want to // set certain field, you can return false before putting // the value into the inner dictionary public override bool TrySetMember(SetMemberBinder binder, object value) { if (binder.Name.Equals("Rating")) return false; dictionary[binder.Name] = value; return true; } public DynamicProxy(T object) { _object = object; dictionary["Name"] = object.GetName(); dictionary["Gender"] = object.GetGender(); dictionary["Interests"] = object.GetInterests(); dictionary["Rating"] = object.GetGeekRating(); } public string GetName() { return (string)dictionary["Name"]; } public int GetGeekRating() { return (int)dictionary["Rating"]; } } 

Then on the driver class:

dynamic dynamicProxy = new DynamicProxy(person); 

That way, you can set and get the fields with access control.

Comments

0

For adding any functionality before and after of every function in a class, Real proxy is a good approach.

So now in T can be any TestClass. Create Instance like this for TestClass-

var _instance=(object)DynamicProxy(TestClass).GetTransparentProxy();

The code for Dynamic Proxy-

 class DynamicProxy<T> : RealProxy { readonly T decorated; public DynamicProxy(T decorated) : base(typeof(T)) { this.decorated = decorated; } public override IMessage Invoke(IMessage msg) { var methodCall = msg as IMethodCallMessage; var methodInfo = methodCall.MethodBase as MethodInfo; string fullMethodName = $"{methodInfo.DeclaringType.Name}.{methodCall.MethodName}"; try { var result = methodInfo.Invoke(decorated, methodCall.InArgs); return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall); } catch (Exception e) { return new ReturnMessage(e, methodCall); } finally { } } } 

Comments

0

You can't intercept all calls for static, not virtual, or private members unless you get the CLR to hooks into each every method/property call to that object and redirect call to fake one you created. You can achieve that by using the .NET Profiler API. TypeMock Isolator for example uses it monitor an application's execution and when method is called, CLR notifies typemock isolator which allows Isolator to override the original class completely.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.