Skip to content

Instantly share code, notes, and snippets.

@JohannesRudolph
Created March 30, 2010 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohannesRudolph/349392 to your computer and use it in GitHub Desktop.
Save JohannesRudolph/349392 to your computer and use it in GitHub Desktop.
using System;
using Library;
using System.Reflection;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Services;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Activation;
namespace Library
{
internal interface IRunner
{
void Execute();
}
public sealed class AssemblyRunner : IRunner
{
void IRunner.Execute()
{
Console.WriteLine("executing");
}
}
public class CompositeRunner
{
private readonly Type runnerType;
public CompositeRunner(Type runnerType)
{
this.runnerType = runnerType;
}
public void Execute()
{
if (!typeof(IRunner).IsAssignableFrom(runnerType))
throw new InvalidOperationException("invalid type");
var runner = (IRunner)Activator.CreateInstance(runnerType);
Console.WriteLine("starting");
runner.Execute();
Console.WriteLine("done");
}
}
}
namespace ConsoleApplication1
{
/// <summary>
/// Fakes the type of RunnerProxy.
/// </summary>
public class RunnerProxyType : TypeDelegator
{
public static readonly Type runnerInterfaceType = typeof(AssemblyRunner).Assembly.GetType("Library.IRunner");
private bool hasCheckedAssignableFrom = false;
/// <summary>
/// Initializes a new instance of the RunnerProxyType class.
/// </summary>
public RunnerProxyType() : base(runnerInterfaceType)
{
}
/// <summary>
/// Returns IRunner on the first call and the RunnerProxyHook afterwards.
/// </summary>
public override Type UnderlyingSystemType
{
get
{
if (!hasCheckedAssignableFrom)
{
hasCheckedAssignableFrom = true;
return runnerInterfaceType;
}
// The callee will try to instantiate this
return typeof(RunnerProxyCreationHook);
}
}
}
/// <summary>
/// Intercepts object creation to return a proxy.
/// </summary>
class ActivatorCreateInstanceHook : ProxyAttribute
{
/// <summary>
/// Return a proxy to the callee.
/// </summary>
/// <param name="serverType"></param>
/// <returns></returns>
public override MarshalByRefObject CreateInstance(Type serverType)
{
var proxy = new RunnerProxy();
return (MarshalByRefObject)proxy.GetTransparentProxy();
// after returning the proxy instance will receive a construction message
}
}
/// <summary>
/// Does nothing but providing a hook for object creation.
/// </summary>
[ActivatorCreateInstanceHook]
class RunnerProxyCreationHook : ContextBoundObject
{
}
public class RunnerProxy : RealProxy
{
public static readonly Type runnerInterfaceType = typeof(AssemblyRunner).Assembly.GetType("Library.IRunner");
public RunnerProxy()
: base(runnerInterfaceType)
{
}
public override IMessage Invoke(IMessage msg)
{
IConstructionCallMessage cmsg = msg as IConstructionCallMessage;
if (cmsg != null)
{
// return the proxy again
return EnterpriseServicesHelper.CreateConstructionReturnMessage(cmsg, (MarshalByRefObject)this.GetTransparentProxy());
}
IMethodCallMessage mmsg = msg as IMethodCallMessage;
if (mmsg != null && mmsg.MethodName == "Execute")
{
Console.WriteLine("before executing");
AssemblyRunner r = new AssemblyRunner();
runnerInterfaceType.GetMethod("Execute").Invoke(r, null);
Console.WriteLine("after executing");
return new ReturnMessage(null, mmsg);
}
throw new NotSupportedException();
}
}
class Program
{
static void Main(string[] args)
{
CompositeRunner comprunner = new CompositeRunner(new RunnerProxyType());
comprunner.Execute();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment