如何创建匿名类以便将其传递给通用构造函数?

时间:2016-09-30 14:19:34

标签: c# generics anonymous-types anonymous-class

我将非通用存储库的测试移植到通用存储库。我没有使用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);

我该如何解决这个问题?我没有要求使用匿名对象,我只是认为这将是一种实用的方法来让我的测试运行,但如果这不是一个好的设计,我肯定可以采取其他方式。

3 个答案:

答案 0 :(得分:2)

匿名类型的技巧是通过示例进行转换;让编译器通过利用类型推断为您完成工作:

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

现在你需要做的就是:

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

答案 1 :(得分: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是匿名类型。

答案 2 :(得分: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
}

通过传递您的匿名对象作为参数(即使您不使用它),它允许您将其类型作为通用参数。然后,您可以根据其类型使用它来实例化对象。