处理可选的依赖项(C#)

Jus*_*tin 11 c# dependencies

我们有一个可选择与TFS集成的应用程序,但由于集成是可选的,我显然不希望所有机器都需要TFS程序集作为要求.

我该怎么办?

  1. 我可以在我的主程序集中引用TFS库,并确保在使用TFS集成时只引用TFS相关对象.
  2. 或者,更安全的选择是在一些单独的"TFSWrapper"程序集中引用TFS库:

    一个.那么我可以直接引用该程序集(只要我小心我所说的)

    湾 我应该为我的TFSWrapper程序集公开一组接口来实现,然后在需要时使用反射来实例化这些对象.

1对我来说似乎有风险,另一方面2b看起来过于顶层 - 我本质上是建立一个插件系统.

当然必须有一个更简单的方法.

Chr*_*isW 6

最安全的方法(即在应用程序中不出错的最简单方法)可能如下所示.

创建一个抽象使用TFS的接口,例如:

interface ITfs
{
  bool checkout(string filename);
}
Run Code Online (Sandbox Code Playgroud)

编写一个使用TFS实现此接口的类:

class Tfs : ITfs
{
  public bool checkout(string filename)
  {
    ... code here which uses the TFS assembly ...
  }
}
Run Code Online (Sandbox Code Playgroud)

编写另一个实现此接口的类,而不使用TFS:

class NoTfs : ITfs
{
  public bool checkout(string filename)
  {
    //TFS not installed so checking out is impossible
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

在某个地方有一个单身人士:

static class TfsFactory
{
  public static ITfs instance;

  static TfsFactory()
  {
    ... code here to set the instance
    either to an instance of the Tfs class
    or to an instance of the NoTfs class ...
  }
}
Run Code Online (Sandbox Code Playgroud)

现在只有一个地方需要小心(即TfsFactory构造函数); 其余的代码可以在不知道是否安装了TFS的情况下调用TfsFactory.instance的ITfs方法.


要回答下面的评论:

根据我的测试(我不知道这是否是'定义的行为'),当你调用一个取决于缺少的程序集的方法时,会抛出异常.因此,在程序集中至少在一个单独的方法(或单独的类)中封装代码 - 这取决于缺少的程序集是很重要的.

例如,如果缺少Talk程序集,则不会加载以下内容:

using System;
using OptionalLibrary;

namespace TestReferences
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            if (args.Length > 0 && args[0] == "1") {
                Talk talk = new Talk();
                Console.WriteLine(talk.sayHello() + " " + talk.sayWorld() + "!");
            } else {
                Console.WriteLine("2 Hello World!");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下将加载:

using System;
using OptionalLibrary;

namespace TestReferences
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            if (args.Length > 0 && args[0] == "1") {
                foo();
            } else {
                Console.WriteLine("2 Hello World!");
            }
        }

        static void foo()
        {
            Talk talk = new Talk();
            Console.WriteLine(talk.sayHello() + " " + talk.sayWorld() + "!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这些是测试结果(在Windows上使用MSVC#2010和.NET):

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug>TestReferences.exe
2 Hello World!

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug>TestReferences.exe 1

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'OptionalLibrary, Version=1.0.0.0,
 Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
   at TestReferences.MainClass.foo()
   at TestReferences.MainClass.Main(String[] args) in C:\github\TestReferences\TestReferences\TestReferences\Program.cs:
line 11

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug>
Run Code Online (Sandbox Code Playgroud)