在C#中实现动态代理的最佳方法是什么?

时间:2011-01-04 19:44:39

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

我需要在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要求我将其所有客户端更改为使用'dynamic'而不是'ISecondaryInterface'。

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

更新2

例如:

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

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

5 个答案:

答案 0 :(得分:6)

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

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

  
      
  • 方面#
  •   
  • Encase AOP
  •   
  • Spring.NET
  •   
  • Aspect.NET
  •   
  • AspectDNG
  •   
  • 动态代理
  •   
  • 撰写*
  •   
  • Loom.NET
  •   
  • PostSharp
  •   
     

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

     
      
  • MSIL注入 - 这里我们将MSIL代码注入到主体中   正在执行的方法。 (后尖锐)
  •   
  • 运行时动态注入 - 使用反射等技术   动态调用方法。
  •   
  • 类型构建器注入 - 与运行时注入相关,我们基于创建类型   我们希望代理的类型,然后通过这种类型封送请求。 (动态代理)
  •   
  • 容器注入 - 请求通过容器   它在我们执行方法之前和之后调用代码。
  •   

请参阅full article

我知道 Castle Project 动态代理经常被使用(比如 Moq 只是为了命名一个大型项目)。


回复更新的主题

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

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

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

MySecretProxy<Bar> bar;

答案 1 :(得分:3)

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

它也是开源的,所以你甚至可以根据需要进行分叉。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

城堡

李林甫

Spring ByteCode