Динамический доступ к классам заданного пространства имен - PullRequest
2 голосов
/ 23 мая 2010

Я пишу интерфейс, который будет реализован многими классами, и я пишу класс, который будет содержать коллекцию экземпляров этих реализаций.Каждый класс будет иметь конструктор по умолчанию.

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

Итак, я хотел бы иметь возможность перебирать все классы заданного пространства имен или, возможно, список всех доступных классов.Тогда мой метод просто через рефлексию проверит, реализует ли данный класс заданный интерфейс и, если это так, поместит его в коллекцию.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 23 мая 2010

Вот это без LinQ, разложенного так, чтобы вы могли видеть, что происходит. Но в остальном это точно так же, как то, что написал SLaks.

Он получает все классы, реализующие интерфейс IFoo.

 List<IFoo> items = new List<IFoo>();

//Iterate through all types
foreach (Type type in Assembly.GetExecutingAssembly.GetTypes) {

    //Check the type is public and not abstract
    if (!type.IsPublic | type.IsAbstract)
        continue;

    //Check if it implements the interface IFoo
    if (typeof(IFoo).IsAssignableFrom(type)) {

        //Create an instance of the class
        //If the constructor has arguments put them after "type" like so: 
        //Activator.CreateInstance(type, arg1, arg2, arg3, etc...)
        IFoo foo = (IFoo)Activator.CreateInstance(type);

        //Add the instance to your collection
        items.Add(foo);

    }
}
2 голосов
/ 23 мая 2010

Вам нужно вызвать Assembly.GetTypes(), чтобы получить каждый класс в сборке, вызвать typeof(IMyInterface).IsAssignableFrom, чтобы проверить классы, реализующие интерфейс, затем вызвать Activator.CreateInstanse, чтобы создать экземпляр класса.

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

typeof(IMyInterface).Assembly.GetTypes()
                             .Where<Type, bool>(typeof(IMyInterface).IsAssignableFrom)
                             .Select(t => Activator.CreateInstance(typeof(T)))
                             .ToArray()
...