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
A class or struct can implement multiple interfaces, but a class can only inherit from a single class.
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.
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.
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 =
============= =============
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();
You cannot impose an interface on existing code (unless you use a code weaver like PostSharp, but that's cheating ;-).
Instead, consider these options:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With