1

I have two ServiceReference in my C# app (generated via VisualStudio): ServiceReference1 and ServiceReference2.

Both have the same methods and class names. Their interfaces differ in some methods, but I want only to use methods which have the same interface on both.

How to use them dynamically?

Example:

ServiceReference1.Client clnt1 = new ServiceReference1.Client();
ServiceReference2.Client clnt2 = new ServiceReference2.Client();

string result = "";    
if (type == 1)
   result = clnt1.calculate();
else
   result = clnt2.calculate();

string result2 = "";    
if (type == 1)
   result2 = clnt1.calculate2();
else
   result2 = clnt2.calculate2();

//and so on...

I'm searching for something like this...

ServiceReference1.Client clnt = null;
if (type == 1)
    clnt = new ServiceReference1.Client();
else
    clnt = new (ServiceReference1.Client)ServiceReference2.Client();

string result = clnt.calculate();   
string result2 = clnt.calculate2();  
//and so on...

Since ServiceReference1.Client owns all methods of ServiceReference2.Client (and some more) I thought it should be possible. But it doesn't work.

Using var for the clnt variable also doesn't work, because the Clients are globally defined in the class and var can only be used inside methods.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
netblognet
  • 1,951
  • 2
  • 20
  • 46
  • Could you create a base interface containing the common methods & derive a second interface containing the remainder : http://www.informit.com/articles/article.aspx?p=1336795&seqNum=3 – PaulF Feb 21 '18 at 13:37
  • 3
    Use an `interface`. – Maarten Feb 21 '18 at 13:38
  • VS 2017 has it built into the refactoring (aside from being available in third-party tools like Resharper, of course). `Ctrl-.`, then `Extract interface` and pick your methods. – Jeroen Mostert Feb 21 '18 at 13:41
  • What you are calling an interface is actually a (method) **signature**. An interface is actually the solution to your problem: both classes need to implement the same interface. – Flater Feb 21 '18 at 14:19

1 Answers1

3

I don't know how you are generating these, but most of the time when getting generated code from Visual Studio it is smart enough to declare classes as partial classes.

Visual Studio Generated Code

public partial class ServiceReference1
{
    public string Calculate()
    {
        // Implementation
    }
}

public partial class ServiceReference2
{
    public string Calculate()
    {
        // Implementation
    }
}

If that is the case, what you could do is add your own separate partial class files to the project in order to extend them. In the new files, you could make these classes implement a common interface.

Your Code

public partial class ServiceReference1 : IServiceReference
{
    // Nothing needed here
}

public partial class ServiceReference2 : IServiceReference
{
    // Nothing needed here
}

public interface IServiceReference
{
    string Calculate();
}

Then you can call them like this:

IServiceReference clnt = null;
if (type == 1)
    clnt = new ServiceReference1.Client();
else
    clnt = new ServiceReference2.Client();

string result = clnt.Calculate(); 
//and so on...
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • 1
    This, in combination with the hint from @JeroenMostert that Visual Studio brings its own "extract interface" feature was the solution. Thanks for that! – netblognet Feb 21 '18 at 13:56
  • Jsut one more question. Would this case be a case where the dynamic-keyword (instead of using an interface) was built for? I really never found a use-case where I needed "dynamic". – netblognet Feb 21 '18 at 14:06
  • `dynamic` is another possible solution (see ["duck typing"](https://stackoverflow.com/q/21278078)). However, it comes at a pretty [high performance cost](https://stackoverflow.com/q/7478387) and means you lose Intellisense on variables declared `dynamic`. It is better to use an interface when you **can** and fall back on `dynamic` when you **cannot** use an interface. – NightOwl888 Feb 21 '18 at 14:12
  • Ok, I was a little bit too fast. I've still a problem. The ServiceReference1/2.Clients inherit an abstract class. Now I generated an interface for the Client classes. But this doesn't reflect the methods of the inherited abstract class, but only the methods from the Client classes itself. How to add the methods from the inherited abstract class to the interface? – netblognet Feb 21 '18 at 14:36
  • Can you extract the methods from the abstract class and then copy them into the interface that was extracted from the subclass? If that doesn't work, I suggest you try asking a new SO question so it has better visibility, and you will be more likely to get a suitable answer. – NightOwl888 Feb 21 '18 at 14:40