Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an interface be added to existing .NET types?

My example below involves 2 NET classes which both contain the method CommonMethod. I would like to design MyMethod that can accept either class (Using ) while retaining the functionality common to NetClassA and NetClassB. Case1 would do just that only it is illegal as stated below. Case2 would also accomplish the goal except INetClassA and INetClassB do not exist. Therefore my question is there a way to impose a custom interface (ICommonNetMethods) on existing .NET types (Case 3)? Alternative solutions to my problem are welcomed.

// Case 1:  Illegal because "where" can only have 1 base class
public void MyMethod<Ttype>(Ttype myClass) where Ttype : NetClassA, NetClassB {}

// Case 2:  Legal to utlize multiple "where" interface types
public void MyMethod<Ttype>(Ttype myClass) where Ttype : INetClassA, INetClassB {}

// Case 3:  For this to work ICommonNetMethods must be added to NetClassA/NetClassB
public void MyMethod<Ttype>(Ttype myClass) where Ttype : ICommonNetMethods {}

NetClassA() { This .NET class has method CommonMethod() }
NetClassB() { This .NET class has method CommonMethod() }

interface ICommonNetMethods { void CommonMethod() }

Thanks, aidesigner

like image 814
aidesigner Avatar asked Aug 03 '11 17:08

aidesigner


People also ask

Can an interface implement another class C#?

A class or struct can implement multiple interfaces, but a class can only inherit from a single class.

Can interface inherits from class C#?

C# allows the user to inherit one interface into another interface. When a class implements the inherited interface then it must provide the implementation of all the members that are defined within the interface inheritance chain.

Can an interface be implemented?

An interface can extend any number of interfaces but one interface cannot implement another interface, because if any interface is implemented then its methods must be defined and interface never has the definition of any method.


3 Answers

There are ways to solve this that involve creative thinking.

Most obvious:

Adapter Pattern

You build your interface, then two adapters where each take NetClassA and the other NetClassB. Your common code stays common and the specific lives in the adapters.

This works even for sealed classes. You do not dervice from NetClassA or NetClassB. I kind of want to leave this to you to figure out the implementation, come back in a day if you want the code implementation I'll post it.

Other things to look at:

Extension Methods

and/or

Reflection

More Help

             =====================
             = ICommonNetMethods =
             =====================
                       | (derive)
         |-------------------------------|
====================            ====================
= NetClassAAdapter =            = NetClassBAdapter =
====================            ====================
         | uses (not derive)             | uses (not derive)
   =============                   =============
   = NetClassA =                   = NetClassB =
   =============                   =============
like image 136
Andrew T Finnell Avatar answered Oct 08 '22 12:10

Andrew T Finnell


Use Func<>:

Assume two classes, A and B, each with a function Foo (though this isn't really a requirement for this solution, observe class C, below):

public class A { int Foo() { return 1; } }
public class B { int Foo() { return 2; } }
public class C { int Deviant() { return 3; } }

Then in some code fragment, you will write:

var a = new A();
var b = new B();
var c = new C();
var fs = new Func<int>[] {() => a.Foo(), () => b.Foo(), () => c.Deviant()};

So to use this:

foreach(var func in fs) 
   Console.WriteLine(func());

Which in turn will output:

1
2
3

Lambda functions are a big deal in C#, and a great technology to learn. If you are unfamiliar, and would like to learn more, start at Microsoft's help page.

If you are looking at larger interfaces, consider, as has been mentioned, the adapter pattern. If the idea of wrapping each of your objects with their own concrete adapter classes seems like too much bloat for your buck, then again, Func<> to the rescue.

public interface ISomeInterface
{
   void f1();
   int f2(string p1);
   ...
}

public class FuncImplementation : ISomeInterface
{
   public Action Func_f1 { get; set; }
   public Func<string,int> Func_f2 { get; set; }
   ...
   public void f1() { Func_f1(); }
   public int f2(string p1) { return Func_f2(p1); }
   ...
}

Now you can make new Adapters inline:

var adaptA = new FuncImplementation { Func_f1 = MyF1, Func_f2 = Myf2 };
adaptA.f1();
like image 24
Michael Hays Avatar answered Oct 08 '22 11:10

Michael Hays


You cannot impose an interface on existing code (unless you use a code weaver like PostSharp, but that's cheating ;-).

Instead, consider these options:

  1. If you simply have a single method on your interface, you could use a Delegate instead.
  2. You could make a simple wrapper class for each of your types, and implement the interface there.
like image 5
agent-j Avatar answered Oct 08 '22 13:10

agent-j