1

我有一個項目與兩個類庫。 我需要他們之間的編程像C#開關庫使用程序參數

if(arg == "a") 
    using LibraryA; 
if(arg == "b") 
    using LibraryB; 

namespace Project 
{ 
    public class MyClass 
    { 
    // my code here 
    } 
} 
+3

爲什麼你需要這個?爲什麼不參考他們兩個? –

+0

它非常複雜,你參考兩個庫,稍後根據參數使用它。 – andy

+2

如果您在代碼中引用具體類型(而不是接口),那麼特定的類型或變量在編譯時就會被修復。這些庫之間是否有共同點(大概是命名空間和類型名稱)? –

回答

1

如果你想建立鬆散的夫婦應用程序切換,與應用程序的參數,我建議你閱讀更多關於扶養注塑模式。 這是一個不錯的article,描述如何建立這樣的設計。 (前4節課)

0

這是一個相當複雜的要求,你必須將多種模式結合在一起來實現這一點。我會盡量聯繫相關原則。

要解決的第一個問題是對齊兩個類庫,使它們具有通用接口。這是必要的,以便使它們可以互換,就像你描述的那樣。通常這與創建兩個對象實現的接口一樣簡單 - 但是您提到您只能控制其中一個庫。在這種情況下,您需要利用adapter pattern來強制您無法控制的庫來實現您的通用界面。

說,我們目前在Library1.dllLibrary2.dll(Library1.dll是一個我們有超過控制)有這兩個類...

// in Library1.dll 
public class Foo 
{ 
    public int DoSomething() { ... } 
} 

// In Library2.dll 
public class Foo 
{ 
    public int DoSomething() { ... } 
} 

首先,我們需要定義我們的通用接口。這應該駐留在覈心/共享庫...

// In Shared.dll 
public interface IFoo 
{ 
    int DoSomething(); 
} 

,因爲現在我們有超過庫中的一個控制,我們可以很容易地實現它以通常的方式共同界面...

// In Library1.dll 
public class Foo : IFoo 
{ 
    public int DoSomething() { ... } 
} 

但是由於我們無法控制Library2.dll,我們需要創建一個適配器類。這個類的目的僅僅是實現通用接口,並且所有行爲都委託給真實的Library2.Foo。實際上,這允許我們使Library2.Foo對象實現我們的通用接口。

// In Shared.dll 
public class Foo2Adapter : IFoo() 
{ 
    private Library2.Foo _realFoo; 

    public Foo2Adapter() 
    { 
     _realFoo= new Library2.Foo(); 
    } 

    public int DoSomething() 
    { 
     _realFoo.DoSomething(); 
    } 
} 

現在我們需要修改我們的所有客戶端代碼,以使用通用接口而不是直接使用對象。凡之前,你可能有這樣的事情...

if(arg == "a") 
    using LibraryA; 
if(arg == "b") 
    using LibraryB; 

namespace Project 
{ 
    public class MyClass 
    { 
     public void Bar() 
     { 
      var foo = new Foo(); 

      foo.DoSomething(); 
     } 
    } 
} 

現在你的代碼應該只使用界面......

namespace Project 
{ 
    public class MyClass 
    { 
     public void Bar(IFoo foo) 
     { 
      foo.DoSomething(); 
     } 
    } 
} 

現在我們有一個新的問題,我們怎麼知道哪個版本的IFoo使用?是Library1.Foo還是Shared.Foo2Wrapper

您可以使用dependency injection來解決此問題。控制容器的反轉將爲您提供對象,您可以將其配置爲根據特定條件提供不同類型的對象。這裏有一個psuedocode示例,它使用了一個類似於StructureMap(我個人最喜歡的IoC容器)使用的sytax ...

var container = new IocContainer(); 

if (arg == "a") 
    container.For<IFoo>().Use<Library1.Foo>(); 

else if (arg == "b") 
    container.For<IFoo>().Use<Shared.Foo2Adapter>(); 

var foo = container.GetInstance<IFoo>(); 

現在,當我們調用GetInstance<IFoo>() IoC容器將會給我們回無論是Library1.FooShared.Foo2Wrapper取決於它是如何通過命令行配置。我們現在需要遍歷我們以前有new Foo()的客戶代碼中的所有地方,並將其替換爲container.GetInstance<IFoo>()

我希望能讓你感動:)

-1

下面是一個如何實現你的目標的例子。

using System; 
namespace StackOverflowDemo.Applications.TestFrameworkDemo.Data 
{ 

    public interface IDataSource 
    { 
     string GetTitle(int id); 
    } 

    public class Database: IDataSource 
    { 
     public string GetTitle(int id) 
     { 
      string result; 
      //logic to connect to a database and retrieve a value would go here 
      switch (id) 
      { 
       case 1: result = "DB First Title"; break; 
       case 2: result = "DB Second Title"; break; 
       default: throw new KeyNotFoundException(string.Format("ID '{0}' not found",id)); 
      } 
      return result; 
     } 

    } 
} 

using System; 
using StackOverflowDemo.Applications.TestFrameworkDemo.Data; 
namespace StackOverflowDemo.Applications.TestFrameworkDemo.DataTest 
{ 

    public class DatabaseMock : IDataSource 
    { 
     public string GetTitle(int id) 
     { 
      string result; 
      switch (id) 
      { 
       case 1: result = "DBMock First Title"; break; 
       case 2: result = "DBMock Second Title"; break; 
       default: throw new KeyNotFoundException(string.Format("ID '{0}' not found", id)); 
      } 
      return result; 
     } 

    } 
} 


using System; 
using StackOverflowDemo.Applications.TestFrameworkDemo.Data; 
namespace StackOverflowDemo.Applications.TestFrameworkDemo.Logic 
{ 
    public class SomeBusinessObject 
    { 
     private IDataSource myData; 
     public SomeBusinessObject(IDataSource myData) 
     { 
      this.myData = myData; 
     } 
     public void OutputTitle(int id) 
     { 
      Console.WriteLine(myData.GetTitle(id)); 
     } 
    } 
} 

using System; 
using StackOverflowDemo.Applications.TestFrameworkDemo.Data; 
//using StackOverflowDemo.Applications.TestFrameworkDemo.DataTest; //we don't need the using statement if we use the whole path below, which I think relates to your question 
using StackOverflowDemo.Applications.TestFrameworkDemo.Logic; 
namespace StackOverflowDemo.Applications.TestFrameworkDemo 
{ 
    class Program 
    { 
     public static void Main(string[] args) 
     { 
      IDataSource myData; 
#if(DEBUG) 
      myData = new StackOverflowDemo.Applications.TestFrameworkDemo.DataTest.DatabaseMock(); 
#else 
      myData = new Database(); 
#endif 
      SomeBusinessObject sbo = new SomeBusinessObject(myData); 
      sbo.OutputTitle(1); 
      Console.WriteLine("Done"); 
      Console.ReadKey(); 
     } 
    } 
} 

上嘲笑更多信息,請訪問:http://msdn.microsoft.com/en-us/library/ff650441.aspx

還有的東西負載在Channel9的:http://channel9.msdn.com/search?term=test+driven+development

或者您可能感興趣的是:http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx。它允許你劫持現有對象的方法並用虛擬方法替換它們。我還沒有玩過,但看起來很有希望。