Как добавить ссылку на скрипт C#

Я использую библиотеку 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-приложения. Как я могу получить его для правильного разрешения ссылок?

2 ответа

Решение

Догадаться.

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

Я удивлен, что это не делает это автоматически.

Это ожидаемый образец использования:

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

Я решил эту проблему другим способом, я установил для своего свойства "Копировать локальное" необходимые ссылки и установил значение true и загрузил их в свой Evaluator перед загрузкой своих сценариев.

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

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

Где "локальный путь к зависимости" - это просто имя ссылочного объекта, которое можно найти как строку "Описание" любой ссылочной сборки в вашем проекте.

Другие вопросы по тегам