CSharpScript с использованием внешне определенных типов - невозможно преобразовать из типа A в A - PullRequest
4 голосов
/ 29 апреля 2019

Проблема: Невозможно использовать внешние типы в CSharpScript, потому что он не может преобразовать тип объекта из себя в себя из-за некоторого несоответствия сборки, я думаю.

У меня есть 2проекты.

Общий

using System;

namespace Common
{
    public class Arguments
    {
        public string Text;
    }

    public class Output
    {
        public bool Success;
    }
}

и

CSharpScriptingExperiment

using System;
using System.Collections.Generic;
using Common;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

public class Parameters
{
    public string text;

    public Arguments arguments;
}

namespace CSharpScriptingExperiment
{
    class Program
    {
        static void Main(string[] args)
        {   
            ScriptOptions options = ScriptOptions.Default.WithImports(new List<string>() { "Common" });

            options = options.AddReferences(typeof(Arguments).Assembly);

            // Script will compare the text inside arguments object to the text passed in via function parameters
            var script = CSharpScript.Create(@"
                public class TestClass
                {
                    public Output DoSomething(string text, Arguments args)
                    {
                        return new Output() { Success = args.Text == text };
                    }
                }", options: options, globalsType: typeof(Parameters));

            var nextStep = script.ContinueWith<object>("return new TestClass().DoSomething(text, arguments);");

            // Setup the global paramters object
            Parameters parameters = new Parameters();
            parameters.text = "Hello";
            parameters.arguments = new Arguments()
            {
                Text = "Hello"
            };

            // Run script
            Output output = (Output)nextStep.RunAsync(globals: parameters).Result.ReturnValue;

            Console.WriteLine(output.Success);
            Console.ReadLine();
        }
    }
}

Когда я запускаю CSharpScriptingExperiment Я получаю эту ошибку:

"(1,42): error CS1503: Argument 2: cannot convert from 'Common.Arguments [/Users/username/Projects/CSharpScriptingExperiment/CSharpScriptingExperiment/bin/Debug/netcoreapp2.2/Common.dll]' to 'Common.Arguments [Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]'"

В этой строке:

Output output = (Output)nextStep.RunAsync(globals: parameters).Result.ReturnValue;

Common - это проект .NET Standard 2.0.

CSharpScriptingExperiment - это проект .NET Core 2.2.

Есть идеи?Я видел, как другие люди сталкивались с подобными проблемами, но не нашли решения.

1 Ответ

1 голос
/ 03 мая 2019

Получил работу с небольшим обходным путем.

Существует 2 различных области применения CSharpScript. Одна из них - это обычная область видимости C # для кода внутри функций, классов и т. Д. Вторая - это уникальная особенность CSharpScript, которая представляет собой статическую область видимости. Он позволяет запускать переменные и код, не находясь в классе или функции - что-то вроде REPL.

Проблема заключается в том, что когда объект внешнего типа загружается в статическую область видимости, которая затем, в свою очередь, должна передаваться в функцию, которая принимает аргумент этого типа, представление объекта из статической области видимости и нормальная область видимости incompatbile. Это та промежуточная статическая область, которая вызывает проблему.

Итак, все выглядит так:

Executing Assembly -> Script Static Scope -> Script Normal Scope

И это вызывает проблему выше.

При этом:

Executing Assembly -> Script Normal Scope

или

Script Normal Scope -> Executing Assembly

Все работает отлично.

Таким образом, я могу вернуть объект внешнего типа из функции в исполняющую сборку, но не могу передать объект внешнего типа в функцию, сначала пройдя статическую область видимости.

Обходной путь должен принять object в функции и затем привести объект к внешнему типу внутри функции.

using System;
using System.Collections.Generic;
using Common;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

public class Parameters
{
    public string text;

    public Arguments arguments;
}

namespace CSharpScriptingExperiment
{
    class Program
    {
        static void Main(string[] args)
        {   
            ScriptOptions options = ScriptOptions.Default.WithImports(new List<string>() { "Common" });

            options = options.AddReferences(typeof(Arguments).Assembly);

            // Script will compare the text inside arguments object to the text passed in via function parameters
            var script = CSharpScript.Create(@"
                public class TestClass
                {
                    public Output DoSomething(string text, object arguments)
                    {
                        Arguments args = (Arguments)arguments;
                        return new Output() { Success = args.Text == text };
                    }
                }", options: options, globalsType: typeof(Parameters));

            var nextStep = script.ContinueWith<object>("return new TestClass().DoSomething(text, arguments);");

            // Setup the global paramters object
            Parameters parameters = new Parameters();
            parameters.text = "Hello";
            parameters.arguments = new Arguments()
            {
                Text = "Hello"
            };

            // Run script
            Output output = (Output)nextStep.RunAsync(globals: parameters).Result.ReturnValue;

            Console.WriteLine(output.Success);
            Console.ReadLine();
        }
    }
}

Таким образом, основной вывод заключается в том, что до тех пор, пока объект не проходит через статическую область действия, все работает как положено. Если объект должен пройти через статическую область видимости, обработайте его как объект и приведите внутри целевой функции к тому, чем он должен быть - кажется, что у механизма сценариев есть проблемы с выполнением самого преобразования, и типы в принципе конфликтуют.

Это основано исключительно на тестировании и отладке черного ящика - мне бы хотелось, чтобы команда Roslyn взвесила этого или кого-то, кто работал над внутренними компонентами, чтобы проверить, верна ли моя интуиция и выводы.

Надеюсь, это поможет любому, кто наткнется на это!

...