Контекст: .NET 3.5, VS2008. Я не уверен в названии этого вопроса, поэтому не стесняйтесь комментировать и название :-)
Вот сценарий: у меня есть несколько классов, скажем Foo и Bar, все они реализуют следующий интерфейс:
public interface IStartable
{
void Start();
void Stop();
}
А теперь я хотел бы иметь класс контейнера, который получает IEnumerable ‹IStartable› в качестве аргумента в своем конструкторе. Этот класс, в свою очередь, также должен реализовывать интерфейс IStartable:
public class StartableGroup : IStartable // this is the container class
{
private readonly IEnumerable<IStartable> startables;
public StartableGroup(IEnumerable<IStartable> startables)
{
this.startables = startables;
}
public void Start()
{
foreach (var startable in startables)
{
startable.Start();
}
}
public void Stop()
{
foreach (var startable in startables)
{
startable.Stop();
}
}
}
Итак, мой вопрос: как я могу это сделать без написания кода вручную и без генерации кода? Другими словами, я хотел бы иметь что-то вроде следующего.
var arr = new IStartable[] { new Foo(), new Bar("wow") };
var mygroup = GroupGenerator<IStartable>.Create(arr);
mygroup.Start(); // --> calls Foo's Start and Bar's Start
Ограничения:
- Без генерации кода (то есть без реального текстового кода во время компиляции)
- В интерфейсе есть только недействительные методы, с аргументами или без них.
Мотивация:
- У меня довольно большое приложение, с множеством плагинов с разными интерфейсами. Написание класса «группового контейнера» для каждого интерфейса вручную «перегружает» проект классами.
- Написание кода вручную чревато ошибками
- Любые дополнения или обновления сигнатур в интерфейсе IStartable приведут к (ручным) изменениям в классе «группового контейнера».
- Обучение
Я понимаю, что здесь мне нужно использовать отражение, но я бы предпочел использовать надежную структуру (например, DynamicProxy от Castle или RunSharp), чтобы выполнить подключение за меня.
Есть предположения?