Search code examples
c#genericsinterfacecomposition

Generic Interface with composed interfaces and multiple concrete implementations


I want to use a generic interface, that can take other interfaces as properties, that use a concrete implementation. How do I create the pattern, if possible, and how do I resolve the implementation in the service collection. This is going to be used alongside a unit of work and the repository pattern.

I've been trying different techniques and implementations through code. Some have been able to compile, but at runtime they have not been able to get resolved. Part of the question is - can the approach be done, the other have I not resolved this correctly.

public class GenericInterface<T, U> : IGenericInterface<T, U>
{
    public T InterfaceOne { get; set; }     // IInterfaceOne
    public U InterfaceTwo { get; set; }     // IInterfaceTwo
}

public interface IInterfaceOne
{
    void DoOne();
    void DoTwo();
}

public interface IInterfaceTwo
{
    void DoThree();
    void DoFour();
}

public class ConcreteImplementation : IInterfaceOne, IInterfaceTwo
{
    public void DoOne()
    {
        throw new System.NotImplementedException();
    }

    public void DoTwo()
    {
        throw new System.NotImplementedException();
    }

    public void DoThree()
    {
        throw new System.NotImplementedException();
    }

    public void DoFour()
    {
        throw new System.NotImplementedException();
    }
}

public class Resolver { 

    public void Resolve() {

        // Should be able to use the interfaces and reference the ConcreteImplementation....!?
        // How to resolve in a service collection?
        var genericComposedInterfaces = new GenericInterface<IInterfaceOne, IInterfaceTwo>();
    }
}

The desired result is that it should first serve the purpose and secondly get resolved within the service collection / when it is called.

Update

Thanks for the help. So I think I was caught between two minds of what I was trying to achieve. All I really wanted was one backing class that was exposed via two interfaces that could be combined into one generic interface. I think the following works.

Generic Interface takes two or several interfaces.

public interface ITestGenericInterface<T, U>
{
    T InterfaceOne { get; }
    U InterfaceTwo { get; }
}

public class TestGenericInterface<T, U> : ITestGenericInterface<T, U>
{
    public TestGenericInterface(T interfaceOne, U interfaceTwo)
    {
        InterfaceOne = interfaceOne;
        InterfaceTwo = interfaceTwo;
    }

    public T InterfaceOne { get; }
    public U InterfaceTwo { get; }
}

The interfaces with a class that might be used with the above interface.

public interface IInterfaceOne
{
    void DoOne();
    void DoTwo();
}

public interface IInterfaceTwo
{
    void DoThree();
    void DoFour();
}

public class ConcreteClass : IInterfaceOne, IInterfaceTwo
{
    public void DoOne()
    {
        Console.WriteLine("DoOne()");
    }
    public void DoTwo()
    {
        Console.WriteLine("DoTwo()");
    }

    public void DoThree()
    {
        Console.WriteLine("DoDoThreeOne()");
    }

    public void DoFour()
    {
        Console.WriteLine("DoFour()");
    }
}

Registering in the service collection. I don't think I was registering the interface / implementation correctly before which could have been an issue.

  services.AddScoped<IInterfaceOne, ConcreteClass>();
  services.AddScoped<IInterfaceTwo, ConcreteClass>();
  services.AddScoped(typeof(ITestGenericInterface<,>), typeof(TestGenericInterface<,>));

Trying it out

public interface ITestRunner
{
    void Start();
}

public class TestRunner : ITestRunner
{
    private readonly ITestGenericInterface<IInterfaceOne, IInterfaceTwo> _genericTest;

    public TestRunner(
        ITestGenericInterface<IInterfaceOne, IInterfaceTwo> genericTest
        )
    {
        _genericTest = genericTest;
    }

    public void Start()
    {
        // Interface One 
        _genericTest.InterfaceOne.DoOne();
        _genericTest.InterfaceOne.DoTwo();

        // Interface Two
        _genericTest.InterfaceTwo.DoThree();
        _genericTest.InterfaceTwo.DoFour();
    }
}

I appreciate that this was probably simpler than it sounded in my initial question. As Flavio Francisco put me on the right track with his first answer, I will up vote it and mark as the answer. Hopefully this will help someone else. Many thanks.


Solution

  • Looks that what you are trying to do is something like this:

    public interface IGeneric<T, U>
    {
        T InterfaceOne { get; }
    
        U InterfaceTwo { get; }
    }
    
    public class GenericClass : IGeneric<IInterfaceOne, IInterfaceTwo>
    {
        private readonly IInterfaceOne interfaceOne;
        private readonly IInterfaceTwo interfaceTwo;
    
        public GenericClass(IInterfaceOne interfaceOne, IInterfaceTwo interfaceTwo)
        {
            this.interfaceOne = interfaceOne;
            this.interfaceTwo = interfaceTwo;
        }
    
        public IInterfaceOne InterfaceOne { get { return this.interfaceOne; } }
        public IInterfaceTwo InterfaceTwo { get { return this.interfaceTwo; } }
    }
    
    public class ClassOne : IInterfaceOne
    {
        public void DoOne()
        {
            throw new NotImplementedException();
        }
    
        public void DoTwo()
        {
            throw new NotImplementedException();
        }
    }
    
    public class ClassTwo : IInterfaceTwo
    {
        public void DoFour()
        {
            throw new NotImplementedException();
        }
    
        public void DoThree()
        {
            throw new NotImplementedException();
        }
    }
    

    Resolver:

           IGeneric<IInterfaceOne, IInterfaceTwo> genericClass = new GenericClass(new ClassOne(), new ClassTwo());
    
           genericClass.InterfaceOne.DoOne();
    

    Hope that what you want is it.