Можно ли получить экземпляр каждого класса, который наследуется от интерфейса? - PullRequest
2 голосов
/ 30 июля 2009

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

Вот упрощенный пример того, что я пытаюсь выполнить:

public interface IExample
{
    string Foo();
}

public class Example1 : IExample
{
    public string Foo()
    {
        return "I came from Example1 !";
    }
}

public class Example2 : IExample
{
    public string Foo()
    {
        return "I came from Example2 !";
    }
}

//Many more ExampleN's go here

public class ExampleProgram
{

    public static void Main(string[] args)
    {
        var examples = GetExamples();

        foreach (var example in examples)
        {
            Console.WriteLine(example.Foo());
        }
    }

    public static List<IExample> GetExamples()
    {
        //What goes here?
    }
}

Есть ли способ (за исключением жесткого кодирования) для метода GetExamples вернуть список, содержащий экземпляр каждого класса, унаследованного от интерфейса IExample? Любое понимание, которое вы можете дать, будет высоко оценено.

Ответы [ 4 ]

2 голосов
/ 30 июля 2009

См .: Проверить, является ли класс производным от универсального класса

Также: Реализации интерфейса через Reflection ( это может быть именно то, что вы хотите )

В основном вам просто нужно перечислить все типы в целевой сборке и проверить, реализует ли он интерфейс.

1 голос
/ 30 июля 2009

Основываясь на решении Мэтта, я бы реализовал его примерно так:

public static List<IExample> GetExamples()
{
    return GetInstances<IExample>().ToList();
}

private static IEnumerable<T> GetInstances<T>()
{
    return Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => type.IsClass &&
                       !type.IsAbstract &&
                       type.GetConstructor(Type.EmptyTypes) != null &&
                       typeof (T).IsAssignableFrom(type))
        .Select(type => (T) Activator.CreateInstance(type));
}

Это решение пропускает типы, которые не могут быть созданы, такие как абстрактные классы, производные интерфейсы и классы без открытых (без параметров) открытых конструкторов.

0 голосов
/ 30 июля 2009

Вот как бы я сделал что-то подобное:

    public static List<IExample> GetExamples()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var types = assembly.GetTypes().Where(t => t.GetInterfaces().Any(i => i == typeof(IExample))).ToList();

        List<IExample> returnMe = new List<IExample>();
        foreach (var type in types)
            returnMe.Add((IExample) Activator.CreateInstance(type));

        return returnMe;
    }
0 голосов
/ 30 июля 2009

Вам придется использовать отражение.

Assembly.GetExecutingAssembly должна быть вашей отправной точкой.

РЕДАКТИРОВАТЬ: код, который должен помочь

Type[] types = Assembly.GetExecutingAssembly().GetTypes();
foreach(Type tp in types)
{
    if (typeof(IExample).IsAssignableFrom(tp))
    {
        if (tp.IsInterface == false)
        {
            IExample t = Activator.CreateInstance(tp) as IExample;
            Console.WriteLine(t.Foo());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...