heltonbiker heltonbiker - 2 months ago 6
C# Question

How to create anonymous class so that it can be passed to generic constructor?

I am porting tests of a non-generic repository to a generic one. Instead of using

Repo<MyType>
, I want to test the more abstract methods with
Repo<object>
or something.

I tried to use an anonymous instance, but it didn't work:

[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
}


I tried to infer the class reference from the object, without success too:

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);


How can I solve this? I am not demanding to use anonymous objects, I just thought it would be a pragmatic way to make my tests run, but I sure could do it other way if this is not a good design.

Answer

Instead of this:

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

Make a generic method to create your repository:

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

Usage:

[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
}

By passing your anonymous object as parameter (even if you don't use it), it allows you to get its type as generic argument. Then, you can use it to instantiate the objects depending on its type.