gpt4 book ai didi

c# - 如何动态组合两个接口(interface)传递给RealProxy

转载 作者:行者123 更新时间:2023-11-30 13:47:14 28 4
gpt4 key购买 nike

在对 RealProxy 基础构造函数的调用中,您传递要代理的目标对象的类型。我想做的是动态地将接口(interface)​​添加到代理类型,以便可以将生成的代理类型强制转换为其他接口(interface)。

例如:

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);
}
}
}

因此,为了能够将代理类型转换为 IDisposable,除了 IFoo 之外,我还需要能够发送 IDisposableRealProxy 基础构造函数调用。

本质上,我如何实现这个方法来动态地将 IDisposable 添加到 IFoo 以被代理。

private static Type CombineType(Type type1, Type type2)
{
// How to implement this method, Reflection.Emit????
throw new NotImplementedException();
}

最佳答案

有一种非常简单的内置方法可以实现这一点。然而,如果一个人还不知道它,它实际上是不可发现的:-)

为了能够控制哪些转换操作在从某个 RealProxy 派生类关联\获得的透明代理上有效,RealProxy 需要实现一个额外的接口(interface),即IRemotingTypeInfo .

IRemotingTypeInfo 接口(interface)定义的方法之一是 bool CanCastTo(Type type, object o)。每次尝试将代理对象转换为其他类型时都会调用此方法;转换操作的“目标”类型可通过type 参数访问。

因此,要允许您的代理“实现”多个接口(interface),只需从您希望支持的类型的 CanCastTo() 方法返回 true

请注意,在转换之后,透明代理上的方法调用仍由同一个 RealProxy 实例接收。

要进行更深入的讨论,您可以阅读这篇 MSDN 文章:Create a Custom Marshaling Implementation Using .NET Remoting and 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;
}
}

关于c# - 如何动态组合两个接口(interface)传递给RealProxy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18338259/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com