2016-09-30 44 views
1

我將非通用存儲庫的測試移植到通用存儲庫。而不是使用Repo<MyType>,我想用Repo<object>或其他東西來測試更抽象的方法。如何創建匿名類,以便它可以傳遞給通用構造函數?

我試圖用匿名實例,但沒有奏效:

[Test] 
    public void AddToRepoIncrementsByOne() 
    { 
     IFile file = new FileFake(); 
     IByteSerializer<object> serializer = new SerializerObjectFake(); 
     repo = new WriteableFileRepository<object>(file, serializer); 

     var obj = new { Name = "test" }; 
     repo.Add(obj); 

     Assert.True(repo.Items.Count() == 1); 
     Assert.AreEqual(repo.Items.Single().Name, obj.Nome); 
     //----------------------------------^^^^ 
     //-------------------compiler error here 
    } 

我試圖推斷對象的類引用,沒有成功過:

 var obj = new { Nome = "teste" }; 

     Type T = obj.GetType(); 

     IArquivo arquivo = new ArquivoFake(); 
     IByteSerializer<T> serializer = new SerializerObjectFake(); 
     //--------------^ 
     repo = new RepositórioArquivoEscrita<T>(arquivo, serializer); 

我該如何解決這個問題?我沒有要求使用匿名對象,我只是認爲這將是一個讓我的測試運行的實用方法,但如果這不是一個好的設計,我肯定可以用其他方式來完成。

+1

而不是'object'爲泛型類型,儘量使用'dynamic',你應該可以訪問你的財產'Name' –

回答

1

取而代之的是:

IByteSerializer<object> serializer = new SerializerObjectFake(); 
repo = new WriteableFileRepository<object>(file, serializer); 

做一個通用的方法來創建你的資料庫:

RepoType<T> CreateRepository<T>(IFile file, T objectForType) 
{ 
    IByteSerializer<T> serializer = new SerializerObjectFake(); 
    return new WriteableFileRepository<T>(file, serializer); 
} 

用法:

[Test] 
public void AddToRepoIncrementsByOne() 
{ 
    IFile file = new FileFake(); 
    var obj = new { Name = "test" }; 
    /*Your type is missing*/ repo = CreateRepository(file, obj); 

    repo.Add(obj); 

    Assert.True(repo.Items.Count() == 1); 
    Assert.AreEqual(repo.Items.Single().Name, obj.Nome); 
    //----------------------------------^^^^ 
    //-------------------no more error here 
} 

通過傳遞您的匿名對象作爲參數(即使你不使用它),它允許你將它的類型作爲泛型參數。然後,您可以使用它根據其類型實例化對象。

+0

在測試情況下,這會使燈具設置更復雜一些。我最終創建了一個TestObject類,它將使用它來代替匿名,因爲我認爲這是針對我的情況的正確設計,但我認爲你的回答最符合我的要求。謝謝!! – heltonbiker

1

爲解決這個問題的最簡單的方法是通過使用obj,讓編譯器來填補空白的一般方法:

var obj = new { Nome = "teste" }; 
Foo(obj); 

... 

void Foo<T>(T obj) { 
    IArquivo arquivo = new ArquivoFake(); 
    IByteSerializer<T> serializer = new SerializerObjectFake(); 
    // etc 
} 

現在T是匿名類型。

+0

無論如何,只要OP想要訪問那些匿名類型的屬性,他就會因爲在編譯時不知道而被卡住。毛皮序列化,但這當然是不重要的。 – HimBromBeere

2

匿名類型的技巧是通過示例進行投射;讓編譯器做的工作爲你通過利用類型推斷:

public static T CastByExample(this object obj, T prototype) => 
    (T)obj; 

現在,所有你需要做的是:

Assert.AreEqual(repo.Items.Single().CastByExample(obj).Name, obj.Name); 
+0

我喜歡這個,但是我看到的唯一一個,只要你想訪問對象的屬性,就必須施放它。然後,當你拿到你的容器時,你不知道'object'代表什麼類型。所以,對於那些進入你的代碼的人來說,它可能有點混亂。不過,在這種情況下,這應該不成問題。 –

+0

@ romain-aga那麼,人們可能會爭辯說,您總是知道您從回購庫中獲取的物品的有效參考類型;你會如何使用提取的物品? – InBetween

+0

我不能否認,在這種情況下你是對的。即使你可以想象一些奇怪的實現。更常見的情況是,當您將匿名類型存儲在泛型類中時,可能會遇到問題。 –

相關問題