2013-12-04 4 views
1

меня есть интерфейсObservableCollection открытого универсального типа

public interface IImageFilter<TIn, TOut> 
{ 
    // Properties 
    TIn Input { get; set; } 
    string Name { get; set; } 
    Guid Guid { get; set; } 

    TOut Process(TIn frame); 
} 

и мне нужен наблюдаемая коллекция объектов, которые реализуют интерфейс.

private ObservableCollection<IImageFilter<T, U>> _imageFilters; 

объект, который я прохожу к коллекции может быть

IImageFilter<string, string> 
IImageFilter<string, int> 
IImageFilter<int, double> 

Как это объявить _imageFilters? что такое Т? или U?

ответ

2

Не совсем невозможно, Другой подход - использовать Covariant Generic type. Но это потребует некоторых изменений в вашем интерфейсе.

Ваш Интерфейс:

internal interface IImageFilter<out I, out O> 
{ 
    I Input { get; } 

    O Process(); 
} 

Интерфейс Реализация

public class ImageFilter : IImageFilter<string, string> 
{ 
    public string Input { get; private set; } 

    public ImageFilter(string input) 
    { 
     Input = input; 
    } 

    public string Process() 
    { 
     return Input.ToUpper(); 
    } 
} 

Использование:

List<IImageFilter<object, object>> filters= new List<IImageFilter<object, object>>(); 
    ImageFilter filter= new ImageFilter("something"); 
    filters.Add(filter); 
3

Закрывает вы можете получить это

private ObservableCollection<object> _imageFilters; 

Если у вас есть контроль над IImageFilter, вы можете сделать что-то вроде:

public interface IImageFilterBase { 
     object Input { get; set; } 
     string Name { get; set; } 
     Guid Guid { get; set; } 
     object Process(object frame); 
    } 

    public interface IImageFilter<TIn, TOut> : IImageFilterBase { 
     // Properties 
     new TIn Input { get; set; } 
     TOut Process(TIn frame); 
    } 

    public abstract class FilterBase<TIn, TOut> : IImageFilter<TIn, TOut> { 
     public TIn Input { get; set; } 
     public abstract TOut Process(TIn frame); 

     object IImageFilterBase.Input { 
     get { return this.Input; } 
     set { this.Input = (TIn)value; } 
     } 

     public string Name { get;set;} 
     public Guid Guid { get; set; } 

     public object Process(object frame) { 
     return this.Process((TIn)frame); 
     } 
    } 

    // test class 
    public class StringToInt32 : FilterBase<string, int> { 
     public override int Process(string frame) { 
     return Convert.ToInt32(frame); 
     } 
    } 

и объявить сбор как

private ObservableCollection<IImageFilterBase> _imageFilters; 
+0

Мне действительно не хватает этой функции :(. –

2

Конструкции общих интерфейсов в пределах рамок, а также конструкции делегатов (которые обеспечивало квази-общее поведение до появления реальных дженериков), требуют, чтобы весь ген Параметры типа ric заменяются обобщенными дженериками. Можно разработать интерфейсы для использования с генераторами открытой формы, но интерфейсы в рамках этой схемы не подходят.

В качестве простого примера предположим, что кто-то хочет иметь интерфейс, который несколько аналогичен Action<T>, но вместо того, чтобы параметр типа T, он будет принимать один параметр любого типа, который удовлетворяет двум ограничениям, ТС1 и tc2. Можно было бы определить как:

interface ActStatisfyingConstraints<in TC1, in TC2> 
{ 
    void Invoke<T>(ref T param) where T:TC1,TC2; 
} 

Следует отметить, что реализация этого интерфейса сможет передать T как общий параметр для любого другого метода, стесненного его TC1 и TC2, даже если нет ни одного класса который удовлетворяет обоим ограничениям, а также служит базовым классом для всех объектов.

В случае вашей наблюдаемой коллекции вы должны определить интерфейс наблюдателя, который включает методы уведомления, подобные описанным выше. Метод подписки на события будет содержать список ссылок на наблюдателей; добавив что-то в коллекцию, затем вызовите общий метод уведомления о добавленном элементе для каждого элемента в списке.