我们有任选TFS集成的应用,但是作为集成是可选的我显然不希望将所有的机器需要的TFS组件的要求 。
我该怎么办?
- 它是确定由我来引用TFS库在我的主要组件和公正,确保当我使用TFS集成,我只能引用TFS相关的对象。
可替换地,更安全的选择将是引用TFS库在一些单独的“TFSWrapper”组件:
一个。 它是那么好,我来(只要我小心再次约我所说的)直接引用该程序集
湾 我应该改为公开一组接口为我TFSWrapper组装来实现,然后使用反射在需要时实例化的对象。
1似乎有风险的我,在另一面2B似乎过了顶 - 我基本上可以建立一个插件系统。
当然,必须有一个简单的方法。
最安全的方式(即不使你的应用程序中的错误,最简单的方法)可能如下。
让这些抽象的TFS的使用,例如接口:
interface ITfs
{
bool checkout(string filename);
}
写它实现了使用TFS此接口的类:
class Tfs : ITfs
{
public bool checkout(string filename)
{
... code here which uses the TFS assembly ...
}
}
写它实现了在不使用TFS这个接口另一个类:
class NoTfs : ITfs
{
public bool checkout(string filename)
{
//TFS not installed so checking out is impossible
return false;
}
}
有一个单身的地方:
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 ...
}
}
现在,只有一个地方一个需要小心(即TfsFactory构造函数); 你的代码的其余部分可以调用您TfsFactory.instance的ITFS方法不知道是否安装TFS。
要回答以下最近的评论:
根据我的测试(我不知道这是否是“定义的行为”),一个例外是当(只要)抛出调用它取决于缺少的组件的方法。 因此,在汇编封装代码,其中 - 依赖 - 上的缺失装配在至少一个单独的方法(或单独的一类)是很重要的。
例如,如果通话组件缺少以下将不会加载:
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!");
}
}
}
}
以下将加载:
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() + "!");
}
}
}
这些测试结果(在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>
A“插件”的概念可能是要走的路,它也可以让你(后下)扩展您的应用程序,如果需要与其他产品比TFS工作。 选项2a将是多么的“冒险”(当链接文件丢失故障)的选项1。
您可以组装与您的特定用途所需的接口,以及来自您的应用程序和“TFS插件”引用该组件。 后者则提供您接口的实现,并使用TFS来执行操作。 该应用程序可以动态加载的组件,并创建所需要的插件类型的实例(通过激活等)和铸造的那些情况下,以您的接口。
事实上,如果你让那些类型继承MarshalByRef ,你甚至可以将其加载到另一个AppDomain中 ,从而使你的插件的完全分离,也使他们卸。