AppDomain.AppendPrivatePath 替代方案?

发布于 2024-12-28 15:33:23 字数 1133 浏览 5 评论 0原文

我主要通过谷歌阅读了很多东西(不是在这里),但没有找到可以回答我的问题的东西,所以我在这里问。

我确实想添加到“某些东西”(我认为是 AppDomain),以便我的代码可以在运行时解析如何 Assembly.CreateInstance 外部的特定 DLL我的应用程序的编译文件夹。

我真的觉得 AppDomain 是要使用的类,而 AppendPrivatePath 听起来像是要使用的方法,但现在它已经“过时”了...... msdn建议使用PrivateBinPath,但据我了解,我必须创建一个新的AppDomain,并且通过我的测试,我觉得 Assembly.CreateInstance 不会在我的新AppDomain中查找引用

一些代码,例如:

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 时,我得到了一个 TargetInitation 异常,

我也尝试过:

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

这听起来“特别”,但对我来说很好,但它不起作用......

我真的感觉就像我必须提供当前 AppDomain 的 D:\\.....\\bin\\Debug\\ 路径,但由于 AppendPrivatePath 已过时,因此不再可能。 ..

有什么帮助吗?

I read a LOT of things mostly via google (not here on SO) and didn't find something that answer to my question so I'm asking it here.

What I do want to add to "something" (to an AppDomain I think) so that my code can resolve AT RUNTIME how to Assembly.CreateInstance a specific DLL that is outside of my application's compilation folder.

I really feel like AppDomain is the class to use and AppendPrivatePath sounded like the method to use but it now is "Obsolete"...
msdn suggest to use PrivateBinPath but as far as I understood I have to create a new AppDomain and with my tests, I feel like Assembly.CreateInstance doesn't look for references in my new AppDomain

Some code like :

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);

works, but then, when I try to CreateInstance, I got a TargetInvocation exception

I, too, tried :

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

which sounds "special" but good to me, but it doesn't work...

I really feel like I HAVE TO give to D:\\.....\\bin\\Debug\\ path to the current AppDomain but its no longer possible since AppendPrivatePath is Obsolete...

Any help ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等风也等你 2025-01-04 15:33:23

您可以在程序集触发事件时自行解析其他 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
}

You can resolve additional DLLs yourself on an event the assembly fires to let you know that it cannot find a type.

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
}
云归处 2025-01-04 15:33:23

我可能完全跟踪您实际尝试构建的内容,但假设您想要构建一个插件基础架构,您想要在子文件夹中组织插件,如下所示:

\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 预览版),可以非常轻松地构建这样的东西。我认为您甚至可以使用早期版本来做到这一点,但是早期版本迫使您在插件上使用最新版本不再依赖的特殊属性。

所以,假设这是你的插件合同:

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();
    }
}

正如我所说,我可能完全在轨道上,但是寻找替代品的人也可能会发现它很有用:-)

I might be totally of the track what you are actually trying to build but assuming that you want to build a plugin infrastructure where you want to organize plugins in subfolders like this:

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

The problem that you encountered is that that foo.dll fails to load its dependency because the framework does not look in that subdirectory for the assembly to load.

Using the latest preview of the Managed Extensibility Framework (MEF 2 Preview) one can build such things really easy. I assume you could even do that with an earlier version, however earlier versions forced you to use special attributes on your plugins that the most recent version does not depend on any longer.

So, assume that is your plugin contract:

public interface IPlugin
{
    string Run();
}

To load and run all plugins in \plugins\foo\, \plugins\bar\, (...) just use this code:

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();
    }
}

As I said, I might be totally of the track but chances are also that someone looking for an alternative finds it useful :-)

美人迟暮 2025-01-04 15:33:23

怎么样使用

Assembly.LoadFrom("..path)

How about using

Assembly.LoadFrom("..path)
合久必婚 2025-01-04 15:33:23

您可以将 EventHandler 添加到 Appdomains AssemblyResolve 事件,然后从特殊的私有路径加载程序集。

You could add an EventHandler to the Appdomains AssemblyResolve event and then load your assemblies form your special private path.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文