【问题标题】:What's the best way to implement a dynamic proxy in C#?在 C# 中实现动态代理的最佳方法是什么?
【发布时间】:2011-06-03 14:50:06
【问题描述】:

我需要在 C# 中创建一个动态代理。我希望这个类包装另一个类,并采用它的公共接口,转发对这些函数的调用:

class MyRootClass
{
    public virtual void Foo()
    {
        Console.Out.WriteLine("Foo!");
    }

}

interface ISecondaryInterface
{
    void Bar();
}

class Wrapper<T> : ISecondaryInterface where T: MyRootClass
{
    public Wrapper(T otherObj)
    {
    }

    public void Bar()
    {
        Console.Out.WriteLine("Bar!");
    }
}

这是我想使用它的方式:

Wrapper<MyRootClass> wrappedObj = new Wrapper<MyRootClass>(new MyRootClass());
wrappedObj.Bar();
wrappedObj.Foo();

生产:

Bar!
Foo!

有什么想法吗?

最简单的方法是什么?

最好的方法是什么?

非常感谢。

更新

我尝试遵循 Wernight 的建议并使用 C# 4.0 动态代理来实现这一点。不幸的是,我仍然被困住了。代理的重点是模仿(通常,通常)预期的其他接口。使用 DynamicObject 需要我将它的所有客户端更改为使用“动态”而不是“ISecondaryInterface”。

有没有办法获得一个代理对象,这样当它包装一个 A 时,它(静态地?)宣传它支持 A 的接口;当它包装一个B时,它会宣传支持B的接口?

更新 2

例如:

class MySecretProxy : DynamicObject, ISecondaryInterface
{
    public override void TryInvokeMember(...) { .. }

    // no declaration of Bar -- let it be handled by TryInvokeMember
 }

【问题讨论】:

  • 你怎么会得到这样的东西来编译? Wrapper 没有 Foo 方法....

标签: c# .net .net-3.5 dynamic-programming dynamic-proxy


【解决方案1】:

.NET 4 DynamicObject 可以帮助您实现这一目标。

早期的.NET框架可以使用:

  • 方面#
  • 封装 AOP
  • Spring.NET
  • Aspect.NET
  • AspectDNG
  • 动态代理
  • 撰写*
  • Lo​​om.NET
  • PostSharp

这些框架中的每一个都使用一个数字 代码注入技术 在执行之前和之后 方法。这些一般分为4 类别。

  • MSIL 注入 – 这里我们将 MSIL 代码注入到 正在执行的方法。 (发帖)
  • 运行时动态注入——我们使用反射等技术 动态调用方法。
  • 类型构建器注入 - 与运行时注入相关,我们创建一个基于 我们希望代理的类型,然后通过这种类型编组请求。 (动态代理)
  • 容器注入 – 请求通过容器 它在我们的方法被执行之前和之后调用代码。

请参阅full article

我知道 Castle ProjectDynamic Proxy 经常被使用(例如在 Moq 中只是为了命名一个大型项目)。


回复更新的主题

你写的不会编译。 动态 代理是运行时生成的代码,因此您必须以某种方式创建要代理的类的具体实例。可能您正在寻找AOP(面向方面​​的编程)。

class MySecretProxy<T> : DynamicObject, T where T : new()
{
    private T _instance = new T();

    public override void TryInvokeMember(...) { ... }
}

MySecretProxy<Bar> bar;

【讨论】:

  • 关于该主题的精彩文章,以及很好的真实示例。但我仍然无法解决我的问题(请参阅相关更新)。
  • 你的代码没有编译,它给出错误“不能从'T'派生,因为它是一个类型参数”
【解决方案2】:

您看过 Castle 项目的 DynamicProxy 吗?它可能会提供您最终想要实现的目标。见http://www.castleproject.org/dynamicproxy/index.html

它也是开源的,所以如果需要你甚至可以分叉它。

【讨论】:

  • 我简单地看了看,这让我在这里问了一个问题:“最简单的方法是什么?”。它看起来像一个相当大的库,我只打算使用一个小功能。有没有更简单的方法?
  • 您为什么担心图书馆的规模?您只需要使用您想要的功能。物理上,文件 (Castle.Core.dll) 只有 290KB。如果该库可以满足您的需求,那么使用它几乎肯定会比自己重新发明这个特定的轮子更容易。
  • 总的来说,我指的不是程序集的大小,而是需要学习和内化才能正确使用的类/接口的绝对数量。这是一个培训问题,而不是空间问题。
  • 如果您只打算使用库的“一个小功能”,那么为什么您必须同时了解所有其他“功能”?如果您目前对它们不感兴趣,您可以忽略它们。这就像反对使用 .NET 框架本身的库的“一个小功能”,例如mscorlib,只是因为它还有很多其他的“功能”。
【解决方案3】:

如果目标类型是接口或派生自 MarshalByRefObject,您可以使用 RealProxy 执行此操作。

【讨论】:

    【解决方案4】:

    您可能想查看包含动态代理机制的linfu

    【讨论】:

      【解决方案5】:

      我知道 nhibernate 用于延迟加载的代理

      城堡

      临府

      Spring 字节码

      【讨论】:

        猜你喜欢
        • 2013-08-10
        • 1970-01-01
        • 1970-01-01
        • 2011-05-24
        • 1970-01-01
        • 2011-01-04
        • 2010-09-12
        • 1970-01-01
        • 2013-02-21
        相关资源
        最近更新 更多