views:

148

answers:

4

I have an two interfaces defined as follows:

public interface IFoo
{
...
}

Public interface IFooWrapper<T> where T : IFoo
{
  T Foo {get;}
}

I want to be able to declare a collection of IFooWrappers but I don't want to specify the implementation of IFoo.

Ideally I want to do something like the:

IList<IFooWrapper<*>> myList;

I can't figure out a way around this.

+2  A: 
public interface IFoo
{
...
}

public interface IFooWrapper : IFoo
{
...
}
public interface IFooWrapper<T> : IFooWrapper
 where T : IFoo
{
...
}
IList<IFooWrapper> myList;

this is a way to do what you want

ArsenMkrt
My first thought.
280Z28
+2  A: 

What's wrong with

IList<IFooWrapper<IFoo>> myList?
Preet Sangha
Indeed!List<IFooWrapper<IFoo>> myList = new List<IFooWrapper<IFoo>>();
locster
Except that it won't work... for instance, IFooWrapper<Foo> doesn't inherit IFooWrapper<IFoo>, even if Foo implements IFoo... (except if you're using C# 4 which implements covariance)
Thomas Levesque
List<IFooWrapper<IFoo>> fooWrapperList = new List<IFooWrapper<IFoo>>();IFooWrapper<IFoo> concreteWrapper = new ConcreteFooWrapper<IFoo>();fooWrapperList.Add(concreteWrapper);
locster
I appreciate the covariance issue. but the question was about a general iList.
Preet Sangha
A: 
public class FooWrapper : IFooWrapper<IFoo>
DanDan
A: 

What I'm about to suggest is overkill for most situations, since usually you can create an interface higher up in the hierarchy that you can use. However, I think this is the most flexible solution in some ways, and the most faithful representation of what you want:

public interface IFooWrapperUser<U> {
    U Use<T>(IFooWrapper<T> wrapper);
}

public interface IFooWrapperUser {
    void Use<T>(IFooWrapper<T> wrapper);
}

public interface IExistsFooWrapper {
    U Apply<U>(IFooWrapperUser<U> user);
    void Apply(IFooWrapperUser user);
}

public class IExistsFooWrapper<T> : IExistsFooWrapper {
    private IFooWrapper<T> wrapper;
    public IExistsFoo(IFooWrapper<T> wrapper) {
        this.wrapper = wrapper;
    }

    public U Apply<U>(IFooWrapperUser<U> user) {
        return user.Use(foo);
    }

    public void Apply(IFooWrapperUser user) {
        user.Use(foo)
    }
}

Now you can create an instance of an IList<IExistsFooWrapper> which can be used as if it's an IList<IFooWrapper<*>>. The downside is you'll need to create a class to encapsulate the logic you want to run on each element:

private class FooPrinter : IFooWrapperUser<string> {
    public string Apply<T>(IFooWrapper<T> wrapper) {
        return wrapper.Foo.ToString();
    }
}

...
    IFooWrapperUser<string> user = new FooPrinter();
    foreach (IExistFooWrapper wrapper in list) {
        System.Console.WriteLine(wrapper.Apply(user));
    }

...
kvb