Doug Peters
Doug Peters

Reputation: 529

Cast a class as implementing interface

I have a class that implements two interfaces:

public class MyService : IServiceA, IServiceB

Interface IServiceA is exactly the same as IServiceB, but when MyService is instantiated as each of these interfaces, a set of different values that act as MyService's parameters are loaded into memory:

public static string ServiceIdentifier;
IServiceA myService = new MyService(); // ServiceIdentifier should equal to: "A"
IServiceB myService = new MyService(); // ServiceIdentifier should equal to: "B"

What I've tried so far:

public class MyService
{
   public MyService()
   {
      if (this is IServiceA)
      {
        ServiceIdentifier = "A"
      }
      if (this is IServiceB)
      {
        ServiceIdentifier = "B"
      }
   }
}

But that doesn't seem to work, as in both cases it returns: "A", I guess because MyService implements both interfaces so the first if argument in Test() will always be true.

How do I deal with this without having to go with dependency injection etc?

Edit1: The problem I'm trying to solve is that many global parameters must have different value which I would like to be dependent to the way MyService is being instantiated, without having to inject this information to its constructor all the time.

Upvotes: 0

Views: 156

Answers (3)

Neil T
Neil T

Reputation: 3285

As Samuel says, you cannot instantiate an interface. What you can do is declare a variable of an interface type, as in:

IServiceA myService;

to which you can assign an object of any type that implements that interface. When you then assign the variable like this (note the 'new' keyword absent from your code):

IServiceA myService = new MyService();

you are setting myService to be of type MyService (which is fine because MyService implements IServiceA).

However, the constructor of MyService doesn't know about the type of variable to which the instance will be assigned, so there's no (sensible) way you can use the constructor to assign to a property like this.

In fact, if IServiceA and IServiceB are identical then you are going to have some problems anyway. Let's say they both declare a property:

bool Test { get; set; }

Then within MyService, or any other class implementing both interfaces, you'll need to refer to this property as IServiceA.Test or IServiceB.Test - which I'm sure isn't what you want to do.

I'm sure there's a better way of doing what you're trying to achieve, but it would be helpful if you could explain a little more of the motivation behind it so we can try to help.

EDIT:

I'm trying to guess what you're after, but have a look at this. Suppose we define a single interface:

public interface IMyService
{
    string Name { get; }
}

and two classes:

public class MyServiceA : IMyService
{
    public string Name
    {
        get
        {
            return "A";
        }
    }
}

public class MyServiceB : IMyService
{
    public string Name
    {
        get
        {
            return "B";
        }
    }
}

Then we can write a program like this:

private static void Main(string[] args)
{
    IMyService testService;

    testService = new MyServiceA();
    Console.WriteLine(testService.Name);   // prints 'A'

    testService = new MyServiceB();
    Console.WriteLine(testService.Name);   // prints 'B'

    Console.ReadLine();
}

So the local variable testService has been declared as of type IMyService, but can be assigned an object of type MyServiceA or MyServiceB (since both implement the interface). You can then call the interface property Name without knowing the exact type of that object, as shown in this example, and you'll get back either 'A' or 'B' depending upon the actual type of testService.

I hope this is clear?

EDIT 2 (following the edit to the question):

You want MyService to have different a 'state' depending on the way that it's instantiated, but you don't want to pass this information to the constructor? Then how do you want MyService to know what it's supposed to do?

Of course, you wouldn't have to pass all the information in the constructor. You could define the MyService class like this:

 public class MyService
 {
     public MyService(string letter)
     {
         if (letter == "A")
         {
             this.Name = "Service A";
             // Set other property values for service A
         }
         else if (letter == "B")
         {
             this.Name = "Service B";
             // Set other property values for service B
         }
         else
         {
             throw new NotImplementedException();
         }
     }

     public string Name { get; set; }
 }

and then write your program like this:

 private static void Main(string[] args)
 {
     MyService testService;

     testService = new MyService("A");
     Console.WriteLine(testService.Name);   // prints 'Service A'

     testService = new MyService("B");
     Console.WriteLine(testService.Name);   // prints 'Service B'

     Console.ReadLine();
 }

So by passing a one-character string to the constructor (and there are better ways, this is just an example / proof of concept) you can achieve what you need to do without an interface in sight.

Upvotes: 1

jksemple
jksemple

Reputation: 257

If you define a class as implementing two interfaces then every instantiation of that class will implement both interfaces. You don't change what the class implements by assigning its reference to a variable of type IServiceA or IServiceB. If you have a variable of type IServiceA you are simply restricting the functionality/properties that you can access in the underlying object to the set defined as IServiceA.

It's not clear what you are trying to achieve here but perhaps you don't need to use interfaces at all. If you simply construct your MyService object with a property that says what sort of Service it is and save that in the constructor as a private member variable you can then access that member variable through a readonly property later on in the object's life as you wish.

Upvotes: 1

sloth
sloth

Reputation: 101042

Not exactly clear what you're trying to do, but have a look at explicit interface implementations.

Example implementation:

interface IServiceA
{
    void DoSomething();
}
interface IServiceB
{
    void DoSomething();
}
class MyService : IServiceA, IServiceB
{
    void DoSomething(string parameter)
    {
        Console.WriteLine("I'm " + parameter);
    }

    void IServiceA.DoSomething()
    {
        DoSomething("service A");
    }

    void IServiceB.DoSomething()
    {
        DoSomething("service B");
    }
}

Test:

void Main()
{
    var service = new MyService();

    IServiceA serviceA = service;
    serviceA.DoSomething();

    IServiceB serviceB = service;
    serviceB.DoSomething();
}

Output:

I'm service A
I'm service B

Maybe you should explain what your actual problem is so a better solution can be found.

Upvotes: 1

Related Questions