How can I write a factory for services that implement a generic interface?

46 Views Asked by At

Given a set of services that each implement a generic interface where the type parameters all have a common base, how can I write a factory method to return an instance of one of these services? There seems to be no way to write a return type for the factory method.

Here is the sample code, with the problematic method at the bottom:

public abstract class Base
{
    public int BaseProp { get; set; }
}

public class Derived1 : Base
{
    public int DerivedProp1 { get; set; }
}

public class Derived2 : Base
{
    public int DerivedProp2 { get; set; }
}

public interface IHandleStuff<T> where T : Base
{
    T GetStuff();
    void DoStuff(T t);
}

public class Service1 : IHandleStuff<Derived1>
{
    public Derived1 GetStuff() => new();
    public void DoStuff(Derived1 t){}
}

public class Service2 : IHandleStuff<Derived2>
{
    public Derived2 GetStuff() => new();
    public void DoStuff(Derived2 t){}
}

public class Consumer
{
    public void DoStuff(Base t)
    {
        var service = GetServiceFor(t);
        service.DoStuff(t);
    }

    private IHandleStuff<Base> GetServiceFor(Base t)
    {
        return t.BaseProp switch
        {
            1 => new Service1(), // Cannot convert expression type 'Service1' to return type 'IHandleStuff<Base>'
            2 => new Service2(), // An explicit cast to IHandleStuff<Base> compiles but fails at runtime
            _ => throw new ArgumentOutOfRangeException()
        };
    }
}

Update:

Someone pointed out in a comment (now deleted) that the issue in the above code can be resolved by making the DoStuff and GetServiceFor methods in the Consumer class generic. This works, but at some point in the real code we have to call into this from a non-generic method which knows only the base type. So the suggestion only defers the problem.

0

There are 0 best solutions below