C# – Instantiate a class depending on a provided interface in a generic class

c++genericsinstantiation

I have a generic function which gets a interface as a type, now in one condition I have to create a new class depending on the interface. I have been thinking about it and a way to solve it would be to use an IoC but I was hoping there would be an other way because an IoC seems a bit like an overkill.

below is an attempt using the visitor pattern:

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, new()
{
    public T GetOrCreate(string id)
    {
        T item = (T)CreateNew(new T(), id);
        return item;
    }
}

If instead of an interface I was getting an object then I could use the visitor pattern to figure out what class to instantiate but I can't seem to figure this out depending on the interface provided.

An other idea I had was if I can make the where declaration like an or?

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, Iabc or Ixyz, new()

I hope the question is clear 🙂

-Mark


Thanks for the reply's.

The problem is that the method can have many different interfaces assigned to it for example:

RepositoryManager class:

private static IMedicament CreateNew(IMedicament emptyType, string id)
{
    return new Medicament { Id = id };
}
private static IRefund CreateNew(IRefund emptyType, string id)
{
    return new Refund { Id = id };
}

RepositoryManager<Iabc> abcRepository = new RepositoryManager<Iabc>();
RepositoryManager<Ixyz> xyzRepository = new RepositoryManager<Ixyz>();

Iabc abc = abcRepository.GetOrCreate("12345");
Ixyz xyz = xyzRepository.GetOrCreate("12345");

so using T item = (T)CreateNew(new T(), id); won't work because I have to tell it that T can either be of type Iabc or Ixyz but when I do that I get the following error:

The call is ambiguous between the following methods or properties: RepositoryManager<T>.CreateNew(IMedicament, string) and RepositoryManager<T>.CreateNew(IRefund, string)

It would be nice if I get this working besides just copying the code several times.

Best Solution

And why doesn't this work?

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz, new()
{
    public T GetOrCreate(string id)
    {
        T item = (T)CreateNew(new T(), id);
        return item;
    }
}

An alternative, if you can't use new() is to pass in a delegate to create the object (or a compatible type):

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz
{
    private Func<T> _tConstructor;

    public RepositoryManager(Func<T> tConstructor)
    {
      this._tConstructor = tConstructor;
    }

    public T GetOrCreate(string id, )
    {
        T item = (T)CreateNew(this._tConstructor(), id);
        return item;
    }
}