I have use a number of solutions to not quite this problem, but similar things.
1- You could derive a custom proxy from RealProxy and take advantage of the call interceptio provided by the .NET remoting infrastructure. The advantage is that this is super easy, but the limitation is that you need to proxy either an interface and use reflection to invoke the members of your inner class or the class being proxied must inherit from MarshalByRrefObject.
While I hesitate to give a code sample, just because it would not be complete, and I will probably get flamed. But here is a ten minute piece of code just to get you pointed to the right classes etc. Beware, I only handle the IMethodCallMessage so this is not complete but should work as a demo.
class LoggingProxy<T> : RealProxy where T : MarshalByRefObject, new()
{
T _innerObject;
public static T Create()
{
LoggingProxy<T> realProxy = new LoggingProxy<T>();
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
private LoggingProxy() : base(typeof(T))
{
_innerObject = new T();
}
public override IMessage Invoke(IMessage msg)
{
if (msg is IMethodCallMessage)
{
IMethodCallMessage methodCall = msg as IMethodCallMessage;
System.Diagnostics.Debug.WriteLine("Enter: " + methodCall.MethodName);
IMessage returnMessage = RemotingServices.ExecuteMessage(_innerObject, msg as IMethodCallMessage);
System.Diagnostics.Debug.WriteLine("Exit: " + methodCall.MethodName);
return returnMessage;
}
return null;
}
}
This can be used as follows
class MyClass : MarshalByRefObject
{
public int Age
{
get;
set;
}
}
MyClass o = LoggingProxy<MyClass>.Create();
o.Age = 10;
The above will log the call to set_Age on the proxied instance of MyClass.
2- Another alternative, but much more work is to create a proxy class that dynamically generates a type derived from the type you pass in and provides implementations of all the methods and properties in the base type. The generated methods etc. will perform the logging call the base class implementation etc. similar to the RealProxy example. Using VS var type you can probably avoid the need to actually inherit from the type and rather use aggregation for this proxy, that way you will still have intelli-sense support and not need to make all the methods/properties virtual. Sorry no example, this is a little too much for now. But you can look at using CodeDom or better yet Reflection.Emit for the dynamic type building. The dynamic code could do something like that proposed in @tvanfosson's answer.
3- And finally you cpuld use DynamicObject to do much of the above, the disadvantage is that you will not have compile time verification of method calls and no intelli-sense. Again, here is a minimal example.
public class DynamicProxy : System.Dynamic.DynamicObject
{
private object _inner;
public DynamicProxy(object inner)
{
_inner = inner;
}
public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
{
System.Diagnostics.Debug.WriteLine("Enter: ", binder.Name);
bool returnValue = base.TryInvokeMember(binder, args, out result);
System.Diagnostics.Debug.WriteLine("Exit: ", binder.Name);
return returnValue;
}
}
Which is used something like the following
dynamic o2 = new DynamicProxy(new MyClass());
o.Age = 10;
There are a few option for rolling your own solution, alternatively you can look at some of the pre-backed solutions. Which is probably a better way to go, but this should give you some insight as to how some of the solutions have possibly been implemented.