Jim*_*Jim 3 c# reflection.emit dynamic realproxy
在对RealProxy基础构造函数的调用中,传递要代理的目标对象的Type.我想要做的是动态地将接口添加到代理类型,以便可以将结果代理类型强制转换为其他接口.
例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
namespace ConsoleApplication17
{
class Program
{
static void Main(string[] args)
{
MyProxy<IFoo> proxy = new MyProxy<IFoo>(new Foo());
IFoo proxiedFoo = (IFoo)proxy.GetTransparentProxy();
// make a proxied call...
proxiedFoo.DoSomething();
// cast proxiedFoo to IDisposable and dispose of it...
IDisposable disposableFoo = proxiedFoo as IDisposable;
// disposableFoo is null at this point.
disposableFoo.Dispose();
}
}
}
public interface IFoo
{
void DoSomething();
}
public class Foo : IFoo, IDisposable
{
#region IFoo Members
public void DoSomething()
{
//
}
#endregion
#region IDisposable Members
public void Dispose()
{
// dispose
}
#endregion
}
public class MyProxy<T> : RealProxy where T : class
{
private T _target;
public MyProxy(T target) :
base(CombineType(typeof(T), typeof(IDisposable)))
{
this._target = target;
}
private static Type CombineType(Type type1, Type type2)
{
// How to implement this method, Reflection.Emit????
throw new NotImplementedException();
}
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
{
return InvokeRemoteCall((IMethodCallMessage)msg, this._target);
}
/// <summary>
/// Invokes the remote call.
/// </summary>
/// <param name="methodCall">The method call.</param>
/// <param name="target">The target.</param>
/// <returns>A <see cref="ReturnMessage"/></returns>
private static IMessage InvokeRemoteCall(IMethodCallMessage methodCall, object target)
{
MethodInfo method = methodCall.MethodBase as MethodInfo;
object callResult = (target != null) ? method.Invoke(target, methodCall.InArgs) : null;
LogicalCallContext context = methodCall.LogicalCallContext;
var query = method.GetParameters().Where(param => ((ParameterInfo)param).IsOut);
ParameterInfo[] outParameters = query.ToArray();
return new ReturnMessage(callResult, outParameters, outParameters.Count(), context, methodCall);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,为了能够投代理的类型IDisposable,我需要能够发送IDisposable除了IFoo在RealProxy基础构造函数调用.
实质上,我如何实现此方法以动态添加IDisposable到IFoo代理.
private static Type CombineType(Type type1, Type type2)
{
// How to implement this method, Reflection.Emit????
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
小智 8
有一种非常简单的内置方式来实现这一目标.但是,如果一个人还不知道它,它实际上是不可发现的:-)
为了能够控制哪些强制转换操作在从某个特定RealProxy类获得的透明代理上有效,RealProxy需要实现一个额外的接口,即IRemotingTypeInfo.
IRemotingTypeInfo接口定义的方法之一是bool CanCastTo(Type type, object o).每次尝试将代理对象转换为其他类型时,都会调用此方法; 可以通过type参数访问强制转换操作的"目标"类型.
因此,要允许代理"实现"多个接口,只需true从CanCastTo()您希望支持的类型的方法返回.
请注意,在转换后,透明代理上的方法调用仍然由同一RealProxy实例接收.
有关更深入的讨论,您可以阅读此MSDN文章:使用.NET Remoting和COM Interop创建自定义封送实现
这是一个完整的例子:
interface IFaceA
{
void MethodA();
}
interface IFaceB
{
void MethodB();
}
class MultiFaceProxy : RealProxy, IRemotingTypeInfo
{
public MultiFaceProxy()
:base(typeof(IFaceA)) {}
public bool CanCastTo(Type fromType, object o)
{
return fromType == typeof(IFaceA) || fromType == typeof(IFaceB);
}
public string TypeName
{
get { return GetProxiedType().FullName; }
set { throw new NotSupportedException(); }
}
public override IMessage Invoke(IMessage msg)
{
// invoke logic
return null;
}
}
class Program
{
static void Main(string[] args)
{
MultiFaceProxy proxy = new MultiFaceProxy();
IFaceA ifa = (IFaceA) proxy.GetTransparentProxy();
// The following now also works thanks to CanCastTo()
IFaceB ifb = (IFaceB)ifa;
}
}
Run Code Online (Sandbox Code Playgroud)