Mohit Mohit - 2 months ago 10
C# Question

Multiple Interfaces in Generic

I have implemented multiple interfaces in where using Generics. Below is my code

public class createGenericClass<T> where T : IWebService,IVoiceService
{
public void CallDoSomeThing(T t, int x, int y)
{
t.DoSomeThing(x, y);
}

public void CallDoSomeThingElse(T t, int a, float b)
{
t.DoSomeThingElse(a, b);
}

}

public interface IWebService
{
void DoSomeThing(int x, int y);
}

public interface IVoiceService
{
void DoSomeThingElse(int a, float b);
}

public class Web_Service : IWebService
{
public void DoSomeThing(int x, int y)
{ }
}

public class Voice_Service : IVoiceService
{
public void DoSomeThingElse(int a, float b)
{ }
}


Now, I am not able to create a instance of the main class in Main method. I was trying but m not able to do.

class Program
{
static void Main(string[] args)
{
createGenericClass<IWebService> obj = new createGenericClass<IWebService>();
}
}


Please suggest.

KAI KAI
Answer

You can solve this problem by using a common interface. That interface will be used by your helper (createGenericClass) class instance, and will be used by your other interfaces which you would like to pass, as well. Let's call it IBaseService.

public class createGenericClass<T> 
    where T : IBaseService // telling T can be only IBaseService and inherited stuff.
{
    public void CallDoSomeThing(T t, int x, int y)
    {
        (t as IWebService)?.DoSomeThing(x, y); // casting and validating
    }

    public void CallDoSomeThingElse(T t, int a, float b)
    {
        (t as IVoiceService)?.DoSomeThingElse(a, b); // casting and validating
    }
}

public interface IBaseService{} // only gives a common parent to other interfaces. Common properties, methods can be included here.

public interface IWebService : IBaseService // inheriting the common interface
{
    void DoSomeThing(int x, int y);        
}

public interface IVoiceService : IBaseService // inheriting the common interface
{
    void DoSomeThingElse(int a, float b);
}

So, you could instantiate your helper class this way:

class Program
{
    static void Main(string[] args)
    {
        var obj = new createGenericClass<IBaseService>();
        obj.CallDoSomeThing(new Web_Service(), 1, 2); // works well
        obj.CallDoSomeThingElse(new Voice_Service(), 3, 4); // works well
    }
}

Note: also, there are several steps which you could use to simplify the usage of you helper class, such as making the helper class static (maybe Singleton) without Generics and use generics only on methods only. This way you wouldn't need to instantiate the class.
However, these "simplifying" modifications' performance and usability would depend on your goals, on the context of usage, on the data and other manager classes you are working with etc..


Edit: (Your task could be solved without Generics)

You said that you don't want to cast the received instances. Since you would like to call different methods on those instances, you are calling those by calling different methods on you helper class. In this case, you don't really need Generics.

This would do the job, without using IBaseService or even Generics.

public class createGenericClass
{
    public void CallDoSomeThing(IWebService t, int x, int y)
    {
        t.DoSomeThing(x, y);
    }

    public void CallDoSomeThingElse(IVoiceService t, int a, float b)
    {
        t.DoSomeThingElse(a, b);
    }
}

EDIT 2: (The double-Generic stuff, which is NOT recommended here)

Since you've asked for it:

public class createGenericClass<T, V>
    where T: IWebService
    where V: IVoiceService
{
    public void CallDoSomeThing(T t, int x, int y)
    {
        t.DoSomeThing(x, y);
    }

    public void CallDoSomeThingElse(V t, int a, float b)
    {
        t.DoSomeThingElse(a, b);
    }
}

Usage:

static void Main(string[] args)
{
    var obj = new createGenericClass<IWebService, IVoiceService>();
    obj.CallDoSomeThing(new Web_Service(), 1, 2);
    obj.CallDoSomeThingElse(new Voice_Service(), 3, 4);
}
Comments