【问题标题】:How to automatically Proxy a DLL(managed) through another DLL(managed)?如何通过另一个 DLL(托管)自动代理一个 DLL(托管)?
【发布时间】:2019-12-16 22:21:54
【问题描述】:

我有一个奇怪的要求,

其实我们的解决方案是这样的:

  • APP.EXE -> MYDLL.DLL

APP.EXE 使用 MYDLL 组装方法。

现在客户端请求实现这个变体:

  • APP.EXE -> MYDLL_PROXY.DLL -> MYDLL.DLL(动态加载)

MYDLL_PROXY.DLL 必须像代理一样运行,因此调用“MYDLL_PROXY.Method1”将加载外部 MYDLL.DLL 并在其上调用 Method1 并返回结果。

类似这样的反射:

    //MYDLL_PROXY.dll
        ass = Assembly.LoadFrom(@"C:\mydll.dll");       
        String MyGenericMethod ="Something"
        Type MyType = ass.GetTypes()[0];
        Object o = Activator.CreateInstance(MyType);
        MethodInfo Method = ass.GetTypes()[0].GetMethod(MyGenericMethod);
        return Method.Invoke(null, new object[] { /* parameters go here */ });

所以,在生气之前,有一种快速的方法来创建一个假的 dll,就像另一个代理一样?

我需要代理所有:方法、属性、事件。

感谢您的帮助。

NB:是一个老项目,必须使用 Framework 2.0


更新

如果反射不是正确的方法,像这样的封装是可能的吗?那么事件呢?

外部DLL:

public class NastyExternalClassInExternalDll
{
    public void Foo() { ... }
}

主DLL:

public interface IFooable
{
    void Foo();
}

public sealed class NastyExternalClassWrapper : IFooable
{
    private readonly NastyExternalClassInExternalDll original;

    public NastyExternalClassWrapper(NastyExternalClass original)
    {
        this.original = original;
    }

    public void Foo()
    {
        original.Foo();
    }
}

【问题讨论】:

  • 是一个老项目,必须使用 Framework 2.0
  • 所以我没有访问动态库的权限:/
  • 为什么还要使用反射?
  • 你建议@DavidBrowne-Microsoft 什么?我已经开发了一个通用接口,所以“main-fake-proxy-dll”和“real-external-dll”实现了,所以现在我被卡住了!我需要“扩展”它,但我不知道如何使用动态加载的 DLL:/

标签: c# dll system.reflection


【解决方案1】:

一种方法是使用您在问题中编写的接口并包装所有方法\属性。对于事件,您还需要在代理中注册它们并采取行动。

另一种方法是重写概念。 这可以通过两种方法实现。

静态:读取原始 dll(使用 cecil、dnlib 等)并针对您鼓励的每个方法或属性,调用您的代理代码,然后继续使用实际代码。毕竟,那个编织,保存dll就大功告成了。 静态方法的缺点是对原始dll的每一次改动,都需要再次运行wrapper。

动态:将 CLR Profiler 附加到原始 dll,并在任何方法或属性调用之前拦截对代码的所有调用。

对于这些方法,我无法在此处进一步深入,因为它会很长,但您可以阅读它们,如果您有具体问题,请告诉我。

【讨论】:

  • 对于重写解决方案,事件呢?比方说,应用程序调用 mydll_proxy.dll 方法“START”,重写为“mydll.dll”:在 mydll 引发“已启动”事件之后开始,但现在我如何将事件传回 mydll_proxy.dll?也许用界面更简单的监听事件?我试着在接下来的几天里专注于这项任务。谢谢大家
  • 几个选项。 1 - 在订户端处理它。如果没有人订阅它,请通过它。否则,处理它就像使用重写技术处理其他方法一样。 2 - 订阅活动。例如,搜索 Delegate.Combine call instruction 并自行订阅。 3 - 为每次调用调用您的代码,搜索 callvirt 指令以调用或 DynamicInvoke 并调用您的代码。
  • 简而言之。每种方法都有其优点和缺点,并且每种方法都有需要考虑的最终情况。如果您可以访问原始 dll 并且您可以更改它,即使其实现一个接口并且原始代码不会更改,那么您的方法可能是最合适的。程序员最容易追上你,因为解决方案的学习曲线很简单。如果有限制和其他要求,有时无法摆脱另一种更具动态性和最大灵活性的方法。
  • 不管怎样,是什么阻止了您从界面开始的解决方案?
  • 除了有时间花在这个任务上之外,是的,我停止处理来自界面的事件,但我认为订阅方式+界面是我可以选择的最好和“干净”的方式。谢谢。
猜你喜欢
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多