2009-12-04 168 views
3

我有一個類,我試圖做單元測試。該類是一個WCF服務類。 (使它成爲一個泛型類不是我的目標。)C# - 構造函數中的類型參數 - 沒有泛型

我有一個在許多方法中實例化的數據訪問層(DAL)類型(稱爲UserDAL)。爲了讓這些方法得到測試,我需要得到這個局部變量的模擬。 (UserDAL的每個實例都有特定於方法的值,因此將其更改爲類級別的變量會導致代碼混亂,因此我寧願不這樣做。)

我在想的是將重載構造函數並傳入一個類型用於本地方法。空的參數構造函數仍然會創建一個普通的UserDAL,但重載的會有一個實現IUserDAL的模擬類型。

我不確定說我想傳入一個類型的語法。請注意,我沒有試圖傳入一個變量,而是一個類型。

例子:

public class MyWCFClass: IMyWCFClass 
{ 
    private TypeParam _myUserDALType; 
    public MyWCFClass() 
    { 
     _myUserDALType = UserDAL; 
    } 
    public MyWCFClass(TypeParam myUserDALType) 
    { 
     _myUserDALType = myUserDALType; 
    } 

    //methods to use it 
    public MyMethod() 
    { 
     IUserDAL userDAL = new _myUserDALType(); 
     //Call method in IUserDAL 
     userDAL.CreateUser(); 
    } 


    // Several similar methods that all need a different UserDAL go here 
    ..... 
} 

所以,我不知道是什麼樣的類型TypeParam的是(我編的),或者如果這種想不到的是甚至有可能。

如果您有一個非泛型解決方案,那就太棒了。

+1

我不想做泛型的原因是因爲所有靜態方法調用必須更新爲使用通用參數(即MyWCFClass .MyStaticMethod)這需要在不應該​​瞭解的項目中引用我的數據訪問層數據訪問層。 (加上我試了一下,我得到一個對象沒有設置爲一個對象錯誤isntance。) – Vaccano 2009-12-04 21:28:06

回答

5

你的意思是Type,使用Activator.CreateInstance創建實例:

public class MyWCFClass: IMyWCFClass 
{ 
    private Type _myUserDALType; 
    public MyWCFClass() 
    { 
     _myUserDALType = typeof(UserDAL); 
    } 
    public MyWCFClass(Type myUserDALType) 
    { 
     _myUserDALType = myUserDALType; 
    } 

    //methods to use it 
    public void MyMethod() 
    { 
     IUserDAL userDAL = (IUserDAL) Activator.CreateInstance(_myUserDALType); 
     //Call method in IUserDAL 
     userDAL.CreateUser(); 
    } 
} 
+2

儘管這個解決方案正是Vaccano要求的,我鼓勵解決方案克里斯和JS Bangs建議:使用InversionOfControl和一個容器(Spring.Net ,Ninject,Structuremaps,Unity,LinFu,你的名字......)以及ctor-injection。同樣在上述解決方案中,如果_myUserDALType沒有默認ctor,則會在運行時拋出異常。 – tobsen 2009-12-04 21:49:32

+0

這些模式的問題是他們認爲變量是一個類級變量。我正在使用的是一種在本地通過多種方法實例化的類型。 (請參閱我的問題。)如果我可以將它移動到單個類級別的變量,那麼所有這些想法(和其他)都將工作得很好! – Vaccano 2009-12-04 21:58:55

+0

感謝代碼Marc。它效果很好! – Vaccano 2009-12-04 21:59:25

5

使用類型,並使用Activator.CreateInstance實例吧:

private Type _myUserDALType; 

IUserDAL userDAL = Activator.CreateInstance(_myUserDALType) as IUserDAL; 
2

如果你想在一個類型傳遞,可以使用Type對象:

public class A 
{ 
    public A(Type classType) 
    { 
    object myObject = Activator.CreateInstance(...classType...); 
    } 
} 

public class B 
{ 
... 
} 

public class C 
{ 
    public static void main(string[] args) 
    { 
    A a = new A(typeof(B)); 
    } 

}

8

您真正需要的是依賴注入,但您可以通過傳入Type參數,然後使用Activator.CreateInstance(Type)在需要時創建該對象。

就做真正的DI(這會使測試變得更容易)而言,我知道Spring.Net工作得很好。

0

在C#中有一個名爲 「類型」 的類型。有了它,你可以創建一個參數並傳入任何有效的類型。

private void MyMethod(Type myType) 
{ 
    //Do something 
} 
3

您真正的問題不在於仿製藥還是缺乏仿製藥。你真正的問題是MyWFCClass正在調用new和該方法。根據Misko Hevery,通過將實現邏輯的類從new中分離出來,可以獲得最佳的可測試性。而不是讓MyWFCClass知道你想要實現並使用反射的類型,只需將IUserDal對象傳遞給構造函數,允許測試工具在需要時傳入模擬對象。

如果出於某種原因,你不能這樣做,而且你不能使用泛型,那麼你必須自己做。將一個Type對象傳遞給構造函數MyWFCClass,然後使用反射來查找並調用所需的構造函數。

+1

+1顯示「Misko Hevery的代碼審查人員指南」 – tobsen 2009-12-04 21:51:42

1

如果IUserDAL定義了您的WCF服務需要完成其工作的接口,爲什麼不把它的實例作爲構造函數參數?由於WCF需要一個默認的構造函數,爲什麼沒有這個默認的構造函數調用你的默認實現的參數化構造函數?

public class MyWCFClass : IMyWCFClass 
{ 
    private readonly IUserDAL _userDAL; 

    public MyWCFClass() 
     : this(new DefaultUserDAL()) 
    { 
    } 

    public MyWCFClass(IUserDAL userDAL) 
    { 
     _userDAL = userDAL; 
    } 
} 

如果您使用的是依賴注入容器,你可以公開爲一個獨立的,並通過使用單滿足參數的構造函數:

public MyWCFClass() 
    this(Container.Instance.Resolve<IUserDAL>()) 
{ 
} 

通過這種方法,您的WCF類擁有一切它需要完成它的工作,但它仍然是單元測試。此外,它不負責創建它的依賴關係,這是一件好事。

+0

「此外,它不負責創建它的依賴關係,這是一件好事。」但現在它直接依賴基礎設施並違反了「集裝箱無知」的最佳實踐,即imho。 – tobsen 2009-12-04 21:57:38

+0

如果WCF提供了一個您可以用來創建服務對象的鉤子,那麼您可以將其掛鉤。否則,我認爲這是兩個邪惡中較小的一個。 – 2009-12-04 22:25:41

1

簡單得多,並與有這個問題的其他應用程序更加一致,將提取的UserDal的接口,那麼你將有更多的東西一樣:

public MyWCFClass() : this(new UserDAL()) 
{ 
} 
public MyWCFClass(IUserDal userDAL) 
{ 
    _myUserDAL = myUserDAL; 
} 

這也更容易依賴使用步噴射框架比你提出的方法,雖然這肯定是一個次要問題

(編輯澄清基於其他意見的替代解決方案)

如果你的DAL是使用後BEC基本上毫無價值ause它被改變了,取而代之的是帶IUserDalFactory的構造函數,用一種方法Create()

+0

唉,這假設_myUserDAL可以是一個類級別的對象。他們的方式,我目前的結構,這是不可能的。 – Vaccano 2009-12-04 22:11:21

相關問題