Перечислите все библиотеки DLL, реализующие определенный интерфейс из GAC - PullRequest
2 голосов
/ 14 апреля 2009

Aloha

Учитывая архитектуру плагинов (C # / .NET 3.5) с плагинами, хранящимися в GAC, как я могу перечислить / загрузить все библиотеки DLL, содержащие типы, которые реализуют мой конкретный интерфейс? Другими словами, я хотел бы выяснить, какие плагины для моего приложения установлены на машине, посмотрев в GAC.

-Edoode

Ответы [ 5 ]

4 голосов
/ 14 апреля 2009

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

3 голосов
/ 14 апреля 2009

Сначала небольшое уточнение: DLL не может реализовать интерфейс. DLL содержит типы, которые могут реализовывать определенный интерфейс. Вот оболочка .NET вокруг fusion.dll, которая позволяет перечислять все сборки в GAC. После загрузки сборки с помощью Assembly.Load вы можете попытаться найти все типы, которые реализуют определенный интерфейс:

foreach (var type in assembly.GetTypes())
{
    var myInterfaceType = typeof(IMyInterface);
    if (type != myInterfaceType && myInterfaceType.IsAssignableFrom(type))
    {
        Console.WriteLine("{0} implements IMyInterface", type);
    }
}
3 голосов
/ 14 апреля 2009

Gac - это просто каталог на вашем компьютере, как и любой другой. Вот типичная разбивка:

c:\windows\assembly\GAC

                   \GAC_32

                   \GAC_MSIL

И, может быть, некоторые другие ..

В каждой из этих папок вы найдете подпапки, в которых хранятся фактические библиотеки DLL. Сначала вам нужно написать рекурсивный метод, чтобы получить все dll-файлы, найденные в \ assembly \, (вы можете легко найти их в Интернете, если вам неудобно делать это самостоятельно). Получив этот список DLL, вы можете перейти к использованию Assembly.LoadFile, чтобы загрузить сборку и проверить все типы, чтобы увидеть, реализуют ли они данный интерфейс.

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

Некоторые ссылки:

Поиск в каталогах.

Загрузка сборок и проверка заданного интерфейса.

Создание нового домена приложений.

1 голос
/ 14 апреля 2009

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

0 голосов
/ 14 апреля 2009

Во-первых, я бы рекомендовал , а не делать это. Для этого вам нужно загрузить все сборки из GAC. Я бы порекомендовал, чтобы ваш пользователь (или администратор, или кто-то еще) сообщал вам, из каких сборок пытаться загрузить (хотя для этого вам может потребоваться список всех опций, возможно, поэтому вы спрашиваете об этом. ..)

Тем не менее, это может сработать, но оно выдает ошибки для нескольких сборок, на которые оно должно работать, и я не уверен, почему .... Кроме того, я не уверен, как определить, где находится GAC - c : \ windows \ assembly используется по умолчанию, но я не знаю, где хранится реальное значение (реестр?)

var targetType = typeof(IComparable);
var errors = new List<Exception>();
var c = Directory.GetFiles(@"c:\windows\assembly", "*.dll", SearchOption.AllDirectories).ToList()
    .ConvertAll(f => Path.GetFileNameWithoutExtension(f))
    .Where(f => !f.EndsWith(".ni"))
    .Distinct().ToList()
    .ConvertAll(f => { try { return Assembly.ReflectionOnlyLoad(f); } catch (Exception ex) { errors.Add(ex); return null; } })
    .Where(a => a != null)
    .SelectMany(a => { try { return a.GetTypes(); } catch (Exception ex) { errors.Add(ex); return new Type[] { }; } })
    .Where(t => targetType.IsAssignableFrom(t));

Удачи с этим.

...