Альтернативой AppDomain.AppendPrivatePath? - PullRequest
4 голосов
/ 25 января 2012

Я прочитал МНОГО вещей в основном через Google (не здесь, на SO) и не нашел что-то, что отвечает на мой вопрос, поэтому я задаю его здесь.

То, что я хочу добавить к «чему-то» (думаю, к AppDomain), чтобы мой код мог РАЗРЕШИТЬСЯ, КАК Assembly.CreateInstance конкретная DLL, которая находится вне папки компиляции моего приложения.

Я действительно чувствую, что AppDomain - это класс, который нужно использовать, и AppendPrivatePath звучит как используемый метод, но теперь он "устарел" ... msdn предлагает использовать PrivateBinPath, но, насколько я понял, мне нужно создать новый домен приложений, и с моими тестами я чувствую, что Assembly.CreateInstance не ищет ссылки в моем новом домене приложений

Какой-то код вроде:

AppDomainSetup domaininfo = new AppDomainSetup();
domaininfo.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domaininfo.PrivateBinPath = "D:\\.....\\bin\\Debug\\";

Evidence adevidence = AppDomain.CurrentDomain.Evidence;

AppDomain newDomain = AppDomain.CreateDomain("FrameworkDomain", adevidence, domaininfo);

работает, но затем, когда я пытаюсь CreateInstance, я получил исключение TargetInvocation

Я тоже попробовал:

Thread.GetDomain().SetupInformation.PrivateBinPath = "D:\\.....\\bin\\Debug\\";

, что звучит "особенным", но хорошо для меня, но не работает ...

Я действительно чувствую, что ДОЛЖЕН дать D:\\.....\\bin\\Debug\\ путь к текущему домену приложений, но это больше невозможно, поскольку AppendPrivatePath устарел ...

Любая помощь?

Ответы [ 4 ]

3 голосов
/ 25 января 2012

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

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += MyResolve;
AppDomain.CurrentDomain.AssemblyResolve += MyResolve;

private Assembly MyResolve(Object sender, ResolveEventArgs e) {
    Console.Error.WriteLine("Resolving assembly {0}", e.Name);
    // Load the assembly from your private path, and return the result
}
2 голосов
/ 21 июня 2012

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

\plugins\foo\foo.dll
\plugins\foo\dependency_that_foo_needs.dll
\plugins\bar\bar.dll
\plugins\bar\dependency_that_bar_needs.dll

Проблема в том, чтоВы столкнулись с тем, что foo.dll не удается загрузить свою зависимость, потому что платформа не ищет в этом подкаталоге загружаемую сборку.

Используя последний предварительный просмотр инфраструктуры управляемой расширяемости (MEF 2 Preview), можностроить такие вещи действительно легко.Я предполагаю, что вы могли бы даже сделать это с более ранней версией, однако более ранние версии заставляли вас использовать специальные атрибуты в ваших плагинах, от которых больше не зависит самая последняя версия.

Итак, предположим, что это ваш плагин-контракт:

public interface IPlugin
{
    string Run();
}

Чтобы загрузить и запустить все плагины в \ plugins \ foo \, \ plugins \ bar \, (...) просто используйте этот код:

class Program
{
    static void Main(string[] args)
    {
        var registration = new RegistrationBuilder();
        registration.ForTypesDerivedFrom<IPlugin>().Export().Export<IPlugin>();

        var directoryInfo = new DirectoryInfo("./plugins");

        var directoryCatalogs = directoryInfo
            .GetDirectories("*", SearchOption.AllDirectories)
            .Select(dir => new DirectoryCatalog(dir.FullName, registration));

        var aggregateCatalog = new AggregateCatalog(directoryCatalogs);

        var container = new CompositionContainer(aggregateCatalog);
        container
            .GetExportedValues<IPlugin>()
            .ForEach(plugin => Console.WriteLine(plugin.Run()));

        Console.ReadLine();
    }
}

Как ясказал, что я мог бы быть полностью на трассе, но есть вероятность, что кто-то ищет альтернативу находит это полезным: -)

0 голосов
/ 25 января 2012

Вы можете добавить EventHandler к событию Appdomains AssemblyResolve, а затем загрузить свои сборки из своего специального личного пути.

0 голосов
/ 25 января 2012

Как насчет использования

Assembly.LoadFrom("..path)
...