Как я могу найти определенный тип в сборке * эффективно *? - PullRequest
5 голосов
/ 11 февраля 2009

Я ищу более эффективный способ найти тип в сборке, который наследуется от известного определенного типа. По сути, в моем приложении есть архитектура плагинов, и мы долгое время занимались этим:

For Each t As Type In assem.GetTypes()
    If t.BaseType Is pluginType Then
        'Do Stuff here'
    End If
Next

Некоторые плагины имеют большое количество типов, и мы начинаем видеть, что это занимает несколько секунд. Есть ли способ, которым я могу просто попросить все типы, которые имеют базовый тип «pluginType»?

EDIT: Я слишком упростил мой пример кода. Я использовал .GetExportedTypes () в моем фактическом коде. Однако многие классы были помечены как общедоступные, так что это не сильно помогало. Я прочесал проекты и пометил все «Друг», за исключением фактического класса плагина, и все еще требуется примерно столько же времени для изучения сборок. Я сократил, возможно, 100 мс от 1,3 секунды (что составляет менее 10%). Это просто минимальное время, с которым мне приходится иметь дело? Я также попробовал предложение «Атрибут сборки», и оно все равно не принесло большой разницы (возможно, снова 100 мс). В остальное время мне приходится платить за динамическую загрузку сборок?

Ответы [ 5 ]

4 голосов
/ 11 февраля 2009

Прежде всего, вы можете попробовать использовать GetExportedTypes(), чтобы сузить список потенциальных типов. Кроме этого, вы не сможете ускорить процесс итерации. Однако вы можете включить основной плагин, который бы указывал точный тип (типы) плагинов в конкретной сборке:

<manifest>
    <plugin type="FooBar.Plugins.BazPlugin, FooBar" />
</manifest>

чтобы вы могли сделать Type.GetType(string)

IPlugin plugin = (IPlugin)Type.GetType("manifest/plugin/@type" /* for the sake of this discussion */);
1 голос
/ 09 декабря 2009

Решение из публикации списка рассылки mono-devel Джонатана Прайора и Plug-in Framework (часть 1): типы маркировки для потребления : использование атрибутов уровня сборки .

Короче, вы бы добавили новый атрибут:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true)]
class PluginAttribute : Attribute {
  public PluginAttribute (Type type) {this.Type = type;}
  public Type Type {get; private set;}
}

Затем укажите этот атрибут на уровне сборки:

[assembly:Plugin (typeof(Plugin1))]
[assembly:Plugin (typeof(Plugin2))]

Затем запросите сборку для всех атрибутов Plugin:

Assembly a = ...;
PluginAttribute[] plugins =
    (PluginAttribute[]) a.GetCustomAttributes (
        typeof(PluginAttribute), true);
foreach (var plugin in plugins)
// plugin.Type is the type to use as a plugin

Это может быть значительно быстрее, чем при использовании Assembly.GetTypes() / Assembly.GetExportedTypes(), как только типы, перечисленные в [assembly:Plugin] атрибутах, действительно нужны быть загруженным, что может значительно уменьшить объем памяти потребляется (в зависимости от количества типов в сборке).

1 голос
/ 11 февраля 2009

Assembly.GetExportedTypes () возвращает только открытые классы. Может ли это помочь?

0 голосов
/ 21 февраля 2014

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

0 голосов
/ 11 февраля 2009

Наша система плагинов использует атрибуты для определения типов плагинов. Затем мы просто сканируем сборку на предмет определенного атрибута.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...