使用 CodeDomProvider 编译到内存时,程序集找不到引用的程序集

发布于 2024-11-26 02:34:11 字数 959 浏览 2 评论 0原文

我正在尝试使用 CodeDomProvider 在运行时将一些代码编译到内存中。

我正在编译的代码引用了一个外部程序集,我将其包含在编译代码时使用的参数中。

当我编译到内存并尝试对 Visual Studio 外接程序中生成的程序集使用反射时,它会引发异常,指出它找不到引用的程序集。

(例外)
“无法加载一种或多种请求的类型。检索 LoaderExceptions 属性以获取更多信息。”

(加载异常)
“{”无法加载文件或程序集“Dynamo.Jiss.Task,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件。":"Dynamo.Jiss.Task, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}"

我尝试使用绝对路径从不同位置引用程序集。

如果从控制台应用程序运行完全相同的代码,则它可以正常工作;如果我不编译到内存,它也可以在加载项中正常工作。
删除对外部程序集的引用以及引用它的代码在编译到内存时也可以工作,因此,正如异常所描述的那样,这可能是加载引用的程序集时出现的问题。

有谁知道为什么编译到内存并引用程序集在插件中不起作用?

它正在运行的 AppDomain 是否有一些限制或者我应该注意的事情? (目前我最好的猜测)

它应该在特定的文件夹中吗?使用相对路径引用?安全设置?需要签名吗?有什么想法吗?


我想要实现的是一种将具有特定扩展名的文件放入项目中并让插件自动编译它的方法,如果它实现了 ITask 接口(来自外部程序集),它将调用一个 Setup() 方法来实现它代码可以挂钩 Visual Studio 事件并在侦听不同事件的同时执行任务/脚本。这样,如果另一个文件发生更改,我可以轻松执行文本模板,或者在不同事件(文档保存、构建等)上组合和缩小文件。

是否已经存在这样的东西(以减轻我的痛苦)? :)

i am trying to compile some code to memory at runtime using a CodeDomProvider.

The code I am compiling have a reference to an external assembly which I include in the parameters used when compiling the code.

When I compile to memory and try to use reflection on the assembly generated in a Visual Studio Add-In it throws an exception saying that it can't find the referenced assembly.

(Exception)
"Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."

(LoaderException)
"{"Could not load file or assembly 'Dynamo.Jiss.Task, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.":"Dynamo.Jiss.Task, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}"

I have tried referencing the Assembly from different places using the absolute path.

The exact same code works fine if it is run from a Console application, and it also works fine in the Add-In if I do not compile to memory.
Removing the reference to the external assembly and the code that reference it also works when compiling to memory, so it probably as the exception describes is a problem with loading the referenced assembly.

Do anyone have an idea why compiling to memory and referencing an assembly isnt working in an Add-In ?

Is there some restrictions within the AppDomain it is running or something that I should be aware of? (my best guess currently)

Should it be in a specific folder? referenced using a relative path? security settings? needs to be signed? any ideas?


What i am trying to achieve is a way to put files with a specific extension in a project and let the addin automatically compile it and if it implements an ITask interface (from the external assembly) it will call a Setup() method that makes it possible for the code to hook into the Visual Studio events and execute tasks/scripts while listening to the different events. This way I can easily execute Text templates if another file is changed, or Combine and Minify files on different events (document saved, build etc.).

Does something like this already exist (to relieve me from the pain) ? :)

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

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

发布评论

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

评论(1

离去的眼神 2024-12-03 02:34:11

发生这种情况很可能是因为您告诉 CodeDom 生成内存中程序集(这实际上是一个谎言,因为它会临时生成到磁盘,加载它,然后删除文件)。关键是,CodeDom 程序集的编译目录与您用来编译它的目录不同。也就是说,如果您在 bin\Debug 中运行,则 CodeDom 程序集将生成到 %temp%。

您可以通过我能想到的两种方法之一来解决此问题:

  1. 将 CodeDom 程序集编译到与执行程序集相同的路径。

    myCodeProvider.GenerateInMemory = false; // 可能没有必要...有一段时间没有尝试过这个
    myCodeProvider.OutputAssembly = string.Format(@"{0}\{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location, "mydll.dll");
    
  2. 处理 AssemblyResolve 事件并向 CodeDom 程序集提供其请求的引用程序集。

    AppDomain.CurrentDomain.AssemblyResolve += OnCurrentDomainAssemblyResolve
    
    私有静态Assembly OnCurrentDomainAssemblyResolve(对象发送者,ResolveEventArgs args)
    {
                    // 这太昂贵了...不要多次执行此操作,或者以更有效的方式加载程序集文件
                    // 另外,如果您用来编译 CodeDom 程序集的代码尚未使用引用的程序集,则这将不起作用
                    // 你应该使用 Assembly.Load(...)
                    foreach(AppDomain.CurrentDomain.GetAssemblies() 中的程序集@ assembly)
                    {
                        if (@ assembly.FullName.Equals(args.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            返回@程序集;
                        }
                    }
    }
    

This is most likely happening because you're telling CodeDom to generate an in-memory assembly (which is really a lie since it's generating temporarily to disk, loading it, then deleting the file). The point is, the compile directory for the CodeDom assembly is not the same as the one you're using to compile it. That is, if you're running in bin\Debug, the CodeDom assembly is being generated to %temp%.

You could solve this in one of two ways I can think of:

  1. Compile the CodeDom assembly to the same path as your executing assembly.

    myCodeProvider.GenerateInMemory = false; // may not be necessary...haven't tried this in a while
    myCodeProvider.OutputAssembly = string.Format(@"{0}\{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location, "mydll.dll");
    
  2. Handle the AssemblyResolve event and provide the CodeDom assembly the referenced assembly it's requested.

    AppDomain.CurrentDomain.AssemblyResolve += OnCurrentDomainAssemblyResolve
    
    private static Assembly OnCurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
    {
                    // this is absurdly expensive...don't do this more than once, or load the assembly file in a more efficient way
                    // also, if the code you're using to compile the CodeDom assembly doesn't/hasn't used the referenced assembly yet, this won't work
                    // and you should use Assembly.Load(...)
                    foreach (Assembly @assembly in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        if (@assembly.FullName.Equals(args.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            return @assembly;
                        }
                    }
    }
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文