Как отразить типы, которые имеют интерфейс дженерика и получают тот тип дженерика

Моя 1-я цель состоит в том, чтобы отфильтровать типы на основе определенного интерфейса с дженериком.

Моя 2-я цель состоит в том, чтобы получить тип самого универсального параметра.

public UserService : IUserService, IDisposable, IExportableAs
{
  ...
}

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

Так, я использую универсальный интерфейс для маркировки типа для экспорта. В этом случае это IUserService. Я делаю это предположение, что некоторый изящный запрос Linq может дать мне, что я хочу. Но, я испытываю немного затруднений.

Вот то, что я имею до сих пор:

assembly.GetTypes()
    .Where(t => t.GetInterfaces().Any(i => 
                i.IsGenericType &&
                i.GetGenericTypeDefinition() == typeof(IExportableAs<>))
            ).ToList()
    .ForEach(t => _catalogs.Add(
            new ComposablePart()
            {
                Name = t.FullName,
                Type = t // This is incorrect
            })
        );

Это работает, но заметьте, что комментарий выше для "Этого является неправильным". Этот тип является производным классом UserService.

В чем я нуждаюсь в своем конечном результате:

  • Универсальный тип передает в IExportableAs (IUserService в этом случае)
  • Тип производного класса (в этом случае, UserService)

Этот вопрос получил хорошее-голосование, как это получило меня близко (как Вы видите выше): Как определить, реализует ли тип определенный универсальный интерфейсный тип, Но, я должен пойти один шаг вперед в нахождении что универсальный тип.

Не стесняйтесь искажать мой linq выше.

Заранее спасибо!

5
задан Community 23 May 2017 в 10:27
поделиться

1 ответ

Понятно

assembly.GetTypes().SelectMany(t => t.GetInterfaces(), (t, i) => new { t, i })
    .Where(ti => ti.i.IsGenericType &&
                 ti.i.GetGenericTypeDefinition() == (typeof(IExportableAs<>)))
    .Select(ti => new ComposablePart() {
        Name = ti.t.FullName,
        Type = ti.i.GetGenericArguments()[0]
    });

[Edit] В волнении я не оставил свою тестовую программу включенной достаточно долго, чтобы вызвать исключение в интерфейсе, не являющемся универсальным. Думал, что .NET Framework там была особенно умен. Исправленный код теперь, когда я знаю, что это не так.

4
ответ дан 15 December 2019 в 00:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: