允许我们的应用调用客户提供的代码来调用我们的代码

时间:2016-12-19 17:11:08

标签: .net dll circular-reference

我正在寻找最简单的解决方案,允许我们的.Net EXE调用第三方提供的DLL。这就是问题 - DLL在我们的代码中调用对象。

.Net中的一个好处是EXE可以用作其他项目中的程序集,就像它是一个DLL。我最初的想法是让他们将EXE导入他们的项目,然后调用其中的函数。

我嘲笑它并且效果很好,但客户不希望它以这种方式工作,他们想要运行我们的应用并让它调用他们的代码,理想情况下在DLL中提供。

现在,如果他们的代码没有调用我们的代码,这将是微不足道的,但是在我试图使一个项目嘲笑这个时,我总是遇到循环引用问题。我知道我可以通过运行时支持避免所有这些,但也许我错过了一个更简单的解决方案?

3 个答案:

答案 0 :(得分:1)

您可以使用反射轻松克服这种情况,并避免应用程序与第三方开发之间的编译时引用:

  1. 定义应放置第三方程序集的位置。
  2. 在#1中定义的位置查找程序集,并在运行时加载它们。
  3. 您可以定义一些应该实现这些第三方程序集的接口来设置程序集入口点。
  4. 找到#3中定义的接口的实现并调用入口点方法(例如:impl.Main())。
  5. 完成!整个第三方程序集已加载到您的应用程序中,它可以与您注入#3接口实现的任何内容进行交互。
  6. 代码示例:

    IService service = new ServiceImpl();
    
    IEnumerable<IAddin> addIns = Directory.GetFiles("<path to third-party assemblies>")
             .SelectMany(file => Assembly.Load(file).GetTypes())
             .Where(type => typeof(IAddin).IsAssignableFrom(type))
             .Select(type => (IAddIn)Activator.CreateInstance(type, new object[] { serviceImpl });
    
    foreach(IAddin addIn in addIns)
    {
         addIn.Main();
    }
    

    某些加载项可能如下所示:

    public interface IAddIn
    {
        void Main();
    }
    
    public class SomeAddIn : IAddIn
    {
        public SomeAddIn(IService service)
        {
             Service = service;
        }
    
        private IService Service { get; }
    
        public void Main()
        {
            // Service will contain whatever you need to interact with the 
            // main app
        }
    }
    

    不要重新发明轮子

    请注意,我已为您提供了一个代码示例,让您了解该方法,但我不会从头开始这样做。

    我期待着:

答案 1 :(得分:0)

将客户需要与之交互的组件提取到自己的程序集中。这甚至可能只是一个接口(为了简洁起见,我们称之为IPlugin,虽然我不知道你的客户是否真的在编写插件)。

public interface IPlugin
{
  void Register();
  void Execute();
}

现在,您的客户使用DLL中的类实现此接口,并将其复制到应用程序的目录(最简单的情况)。

您的应用程序可能会在启动时执行以下操作。

  • 在指定路径中加载程序集(使用Assembly类)。
  • 获取实现界面的程序集中的类型
  • 在需要时实例化并调用Register - 方法

注册时,插件可以订阅应用程序中的事件,或者您的应用程序可以在需要时调用其执行方法。

这可能需要一些额外的工作甚至返工,但它易于维护和简单。 根据您要执行的操作,您可以在调用接口上的方法时将其他类/接口传递给插件。例如,假设一个类Application,它实现了一个接口IApplication,它在interface-dll中定义。 现在,插件可以调用应用程序中的方法,存储对它的引用,并执行允许它们在接口定义中执行的任何操作。

我希望这比我的第一条评论更好理解: - )

干杯

答案 2 :(得分:0)

我不太了解.Net但在我看来,你的循环引用是一个架构问题,而不是编码问题。我确信.Net中有几个配方可以实现依赖倒置或注入。

你需要设计一个中级&#34;类&#34;这将封装其功能并完全隐藏其内部实现。它们应该在启动时为您提供该类的实例,或者在调用代码时作为参数提供。这就像&#34;代表&#34;我确信您在iOS / MacOS / Swift中工作的方法。

如果有许多使用上下文,甚至可能有几个不同的委托类。

你应该负责设计类的方法和属性(它的签名),他们应该负责实例化对象并实现它背后的代码。