Reputation: 1986
Given an interface IFoo
interface IFoo {
void Do();
void Stuff();
}
Let assume there are (legacy) classes Foo1, Foo2, Foo3 all implementing IFoo.
Stuff can be done by using some methods of IFoo, or in case of the newer classes, by just using DoStuff(). Actually, one might look at it as if DoStuff() was "forgotten" on IFoo.
There are also newer Classes FooX (FooY, ...) implementing IFoo2, in additional those has a method DoStuff();
interface IFoo2 : IFoo {
void DoStuff();
}
I need to accept IFoo objects, and be able to "Do Stuff" on it.
//Let us assume foos = new IFoo[] {new Foo1(), new Foo2(), new Foo3(), new FooX()};
void MyMethod(IFoo[] foos){
foreach(foo in foos){
//DoStuff is not defined in IFoo
foo.DoStuff();
}
}
So, I thought to just define an extension method DoStuff() on IFoo for the legacy classes
public static DoStuff(this IFoo self){
self.Do();
self.Stuff();
}
Unfortunately, this extension method is always called, even for FooX.
I Could do something like
public static DoSomeStuff(this IFoo self){
if(self is IFoo2) {
(self as IFoo2).DoStuff()
} else {
self.Do();
self.Stuff();
}
}
void MyMethod(IFoo[] foos){
foreach(foo in foos){
foo.DoSomeStuff();
}
}
However, the method MyMethod reside in a legacy project, currently not yet aware of IFoo2. Is it possible to find a solution without using IFoo2?
Upvotes: 1
Views: 120
Reputation: 32780
IMHO FooX
shouldn't be implementing IFoo
to begin with and some reconsideration should be made of your current arquitecture.
That said, and not knowing exactly what limitations you are fighting against, could you send the IFooX
s through a wrapper? Something like the following:
public class FooXWrapper<T>: IFoo where T: FooX
{
readonly T foo;
bool doCalled;
public FooWrapper(T foo)
{
this.foo = foo;
}
public void Do()
{
doCalled = true;
}
public void Stuff()
{
if (!doCalled)
throw new InvalidOperationException("Must call Do");
foo.DoStuff();
}
}
Its an ugly hack, but given the circumstances...
Upvotes: 0
Reputation: 1469
You can create an abstract subclass that implements the methods Do and Stuff for the classes that at the current time don't implement it.
public abstract class abstractFoo : IFoo
{
public virtual void Do() {}
public virtual void Stuff(){}
}
If you can then inherit from this abstract class
public class Foo: IFoo
{
// interface implementation required
}
becomes:
public class Foo: abstractFoo
{
// interface implementation NOT required
}
Upvotes: 0
Reputation: 5807
You shouldn't extend IFoo
interface, like that. It's break Interface Segregation principle.
If these object represents exactly the same entity in your code you shouldn't use different interfaces for them.
You might create extension method if you want extend functionality of classes which implements interface IFoo
, but don't create second interface which represents the same contract. However if you want to change IFoo
contract - refactor legacy objects (add missing implementation).
Upvotes: 2
Reputation: 354794
As long as your variable has the type IFoo
, the extension method DoStuff
will be called. The usual way of solving this is exactly what you propose in your last paragraph, or ensuring that you use IFoo2
instead of IFoo
in places where you want the newer interface method to be called.
Upvotes: 0