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

发布于 2024-10-10 01:05:09 字数 1227 浏览 11 评论 0原文

我需要在 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
 }

I've got a need to create a dynamic proxy in C#. I want this class to wrap another class, and take on it's public interface, forwarding calls for those functions:

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

Here's how I want to use it:

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

to produce:

Bar!
Foo!

Any ideas?

What's the easiest way to do this?

What's the best way to do this?

Thanks so much.

UPDATE

I tried following Wernight's recommendation and implement this using C# 4.0 dynamic proxies. Unfortunately, I'm still stuck. The point of the proxy is to mimick the other interface which is (normally, usually) expected. Using DynamicObject requires me to change all the clients of this to use 'dynamic' instead of 'ISecondaryInterface'.

Is there a way to get a proxy object, such that when it wraps an A, it advertises (statically?) that it supports A's interface; and when it wraps a B, it advertises that is supports B's interface?

UPDATE 2

For example:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

紧拥背影 2024-10-17 01:05:09

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

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

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

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

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

请参阅完整文章

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


回复更新的主题

您编写的内容将无法编译。 动态代理是运行时生成的代码,因此您必须以某种方式创建要代理的类的具体实例。也许您正在寻找AOP(面向方面​​的编程)。

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

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

MySecretProxy<Bar> bar;

.NET 4 DynamicObject can help you achieving that.

Earlier .NET framework can use:

  • Aspect#
  • Encase AOP
  • Spring.NET
  • Aspect.NET
  • AspectDNG
  • Dynamic Proxy
  • Compose*
  • Loom.NET
  • PostSharp

Each of these frameworks make use of a number
techniques to the injection of code
both before and after execution of a
method. These generally fall into 4
categories.

  • MSIL injection – Here we inject MSIL code into the body of the
    method being executed. (Post sharp)
  • Runtime dynamic injection – Using techniques such as reflection we
    invoke methods dynamically.
  • Type builder injection – Related to runtime injection, we create a type based on
    the type we wish to proxy and then marshal requests through this type. (Dynamic Proxy)
  • Container injection – Requests pass through a container
    which invokes code before and after our method being executed.

See the full article.

I know that Castle Project's Dynamic Proxy is often used (like in Moq just to name one large project).


REPLY TO UPDATED TOPIC

What you wrote will not compile. Dynamic proxies are runtime generated code, so you'll have to create a concrete instance of the class you're proxying some way or another. May be you're looking to do AOP (aspect-oriented programming).

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

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

MySecretProxy<Bar> bar;
妞丶爷亲个 2024-10-17 01:05:09

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

它也是开放的源,以便您甚至可以在需要时分叉它。

Have you looked at the Castle project's DynamicProxy? It may provide what you're ultimately trying to achieve. See http://www.castleproject.org/dynamicproxy/index.html

It's also open source so you could even fork it if required.

不即不离 2024-10-17 01:05:09

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

You can do this with RealProxy if the target Type is an interface or derives from MarshalByRefObject.

水晶透心 2024-10-17 01:05:09

您可能需要查看 linfu,它包含动态代理机制。

You may want to look at linfu which contains a dynamic proxy mechanism.

怪异←思 2024-10-17 01:05:09

的代理

我知道nhibernate用于延迟加载Castle

Linfu

Spring ByteCode

I know the proxies that used by nhibernate for lazy loading

Castle

Linfu

Spring ByteCode

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文