【问题标题】:How to Add a Reference to a C# Script如何添加对 C# 脚本的引用
【发布时间】:2020-11-08 20:14:24
【问题描述】:

我正在使用CS-Script 库来执行动态代码。我不想将它用作脚本引擎,而是想用它来动态地将功能插入到应用程序中。这是托管代码...

using System;
using CSScriptLibrary;
using System.Reflection;
using System.IO;

namespace CSScriptTester
{
    class Program
    {
        static void Main(string[] args)
        {
            // http://www.csscript.net/
            Console.WriteLine("Running Script.");
            CSScript.Evaluator.ReferenceAssembly(Assembly.GetAssembly(typeof(System.Windows.Forms.MessageBox)));
            string code = File.ReadAllText("SomeCode/MyScript.cs");
            dynamic block = CSScript.Evaluator.LoadCode(code);
            block.ExecuteAFunction();
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

这是 SomeCode/MyScript.cs 的内容...

using System;
using System.Windows.Forms;

namespace CSScriptTester.SomeCode
{
    class MyScript
    {
        public void ExecuteAFunction()
        {
            MessageBox.Show("Hello, world!");
        }
    }
}

这很好用。在托管代码中,我不希望托管代码负责指定程序集引用。所以我注释掉CSScript.Evaluator.ReferenceAssembly(Assembly.GetAssembly(typeof(System.Windows.Forms.MessageBox))); 并运行它,我得到了错误...

错误 CS0234:类型或命名空间名称 Forms' does not exist in the namespaceSystem.Windows'。您是否缺少程序集参考?

我知道如果我使用命令行工具执行此操作,我可以将其添加到脚本顶部以添加引用...

//css_reference System.Windows.Forms.dll

但是在 .NET 应用程序的上下文中执行它时似乎被忽略了。我怎样才能让它正确解析引用?

【问题讨论】:

  • 感谢提及 //css_reference,不知道该怎么做!

标签: c# cs-script


【解决方案1】:

想通了。

string code = File.ReadAllText("SomeCode/MyScript.cs");
CSScript.Evaluator.ReferenceAssembliesFromCode(code);       
dynamic block = CSScript.Evaluator.LoadCode(code);
block.ExecuteAFunction();

我很惊讶它不会自动执行此操作。

【讨论】:

  • 我会对它也不会自动执行此操作的原因非常感兴趣。第一个发现的人回到这里:-)
【解决方案2】:

我已经通过另一种方式解决了这个问题,我将所需的引用程序集“复制本地”属性设置为 true,并在加载脚本之前将它们加载到我的评估器中。

我建议这样做,因为它会预编译和存储加载的程序集,从而更快地临时加载脚本。每次加载脚本时,它都不会从 GAC 或其他地方查找引用的程序集,而是简单地拥有它们并尽可能高效地加载脚本。

CSScript.Evaluator.ReferenceAssembly("<local path to dependency>.dll");
IScript script = CSScript.Evaluator.LoadFile<IScript>("<local path to script file");

“本地依赖路径”只是被引用对象的名称,可以作为项目中任何引用程序集的“描述”字符串找到。

【讨论】:

    【解决方案3】:

    这是预期的使用模式:

    IScript script = CSScript.Evaluator.ReferenceAssembly("<local path to dependency>.dll");
                                       .LoadFile<IScript>("<local path to script file");
    

    
    string code = File.ReadAllText("SomeCode/MyScript.cs");
           
    dynamic block = CSScript.Evaluator
                            .ReferenceAssembliesFromCode(code)
                            .LoadCode(code);
    
    block.ExecuteAFunction();
    

    至于“我会对它不会自动执行此操作的原因非常感兴趣”,这是因为此调用可能很昂贵。如果您这样做,脚本引擎将分析每个using 语句并尝试在所有知名位置和GAC 中查找它。它将分析所有可能的//css_* 指令。

    这就是为什么预期的用例是使用显式 API 方法而不是通过脚本代码来引用程序集,即使可以通过方法 ReferenceAssembliesFromCode 来引用。

    但更重要的是,如果脚本引擎自动执行,用户将无法指定程序集探测目录。

    这就是为什么你最好使用这些专用方法来引用组件:

    IEvaluator ReferenceAssembliesFromCode(string code, params string[] searchDirs);
    IEvaluator ReferenceAssembly(string assembly);
    IEvaluator ReferenceAssembly(Assembly assembly);
    IEvaluator ReferenceAssemblyByName(string assemblyPartialName);
    IEvaluator TryReferenceAssemblyByNamespace(string @namespace, out bool resolved);
    IEvaluator ReferenceAssemblyByNamespace(string @namespace);
    IEvaluator ReferenceAssemblyOf(object obj);
    IEvaluator ReferenceAssemblyOf<T>();
    IEvaluator ReferenceDomainAssemblies(DomainAssemblies assemblies = DomainAssemblies.AllStaticNonGAC);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      相关资源
      最近更新 更多