Как вызвать метод с использованием отражения - PullRequest
0 голосов
/ 13 марта 2012

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

var types =AppDomain.CurrentDomain.GetAssemblies().ToList()
            .SelectMany(s => s.GetTypes())
            .Where(t => typeof(IManagerReport).IsAssignableFrom(t));

Console.WriteLine("Processing manager reports..");
foreach(var TheType in types)
{
              //error here
    var temptype = Activator.CreateInstance(TheType) as IManagerReport;

    temptype.Load();
    temptype.Save();
    Console.WriteLine("Saved to: " + temptype.SavePath);
}

Ошибка, которая появляется здесь:

Невозможно создать экземпляр интерфейса

Ответы [ 3 ]

4 голосов
/ 13 марта 2012

Убедитесь, что вы исключаете IManagerReport из списка типов, которые вы выбираете.

var types =AppDomain.CurrentDomain.GetAssemblies().ToList()
            .SelectMany(s => s.GetTypes())
            .Where(t => typeof(IManagerReport).IsAssignableFrom(t)
                        && typeof(IManagerReport) != t
                        && !t.IsInterface
                        && !t.IsAbstract
                        && !t.IsGenericTypeDefinition);

Проблема в том, что в ваших перечисляемых типах вы получаете не только производные типы IManagerReport, но и сам IManagerReport.Вы не можете создать экземпляр интерфейса, только класс.Используйте код, который я разместил, чтобы исключить большинство проблемных элементов, но я все равно добавил бы попытку / улов на Activator.CreateInstance.У вас могут быть производные типы, у которых нет открытого конструктора без параметров.Они также потерпят неудачу.

Завершение вызова в попытку / поймать и продолжить.Я бы сказал, что вы должны учитывать все возможности здесь, но их просто слишком много.Учет нескольких, а также учет возможности того, что создание просто не будет работать по другой причине.

try {
    var temptype = Activator.CreateInstance(TheType) as IManagerReport;
} catch {
    continue;
}
1 голос
/ 13 марта 2012

Попробуйте добавить либо

.Where(t=>t.IsClass)

или

.Where(t=>!t.IsInterface)

на ваш запрос LINQ

1 голос
/ 13 марта 2012

Проблема в том, что IManagerReport соответствует вашему предикату Where и, следовательно, будет одним из значений в операторе foreach.Вам также необходимо отфильтровать интерфейсы в предложении Where

var types =AppDomain.CurrentDomain.GetAssemblies().ToList()
            .SelectMany(s => s.GetTypes())
            .Where(t => typeof(IManagerReport).IsAssignableFrom(t));
            .Where(t => !t.IsInterface && !t.IsAbstract);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...