Как добавить ссылку на скрипт 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 namespace
System.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");
Где "локальный путь к зависимости" - это просто имя ссылочного объекта, которое можно найти как строку "Описание" любой ссылочной сборки в вашем проекте.