Как стать автором
Обновить

Комментарии 15

Кстати для заинтересованных в таких вещах существует открытый и кроссплатформенный проект dotnet/interactive. Я его использовал в юпитере, но можно использовать embedded kernel, как здесь.

Самое важное не рассказали: можно ли, и как именно, передавать «внешние» объекты и функции внутрь скрипта и использовать их из него (догадываюсь, что возможно можно через Variables, может быть можно и как-нибудь красивее).

Одна из перегрузок CSharpScript.Create принимает параметром тип глобального объекта.
Его методы будут доступны из скрипта глобально.(если он не статический то в Create и RunAsync можно сам объект передать)


Script<object> script = CSharpScript.Create(File.ReadAllText(Program.options.Script), options, typeof (ScriptHost), null);
script.RunAsync(scriptHost, null, new CancellationToken()).Wait();
//Уже в скрипте вызываем метод от глобального объекта
StartSession("some-args");

код декомпилированный(не помню где исходники проекта), но смысл должен быть понятен.


Собственно сам студийный C# Interactive работает по такому же принципу поидее, но там глобальный тип это Console.(можно WriteLine писать прям так)

Возможно, там просто в ScriptOptions указан. Если добавить в него System.Console, то можно будет просто написать WriteLine(...), точно так же, как при использовании "using static System.Console".

вы имели в виду WriteLine наверно :)


там несколько способов помоему.
Потому что я использовал явно вариант и с ScriptOptions и с globalsType аргументами.

Да, спасибо, исправил.


Про вариант с globalsType учту.

Спасибо, что напомнили, постараюсь добавить в статью

Я обычно "скриптингом" на C# занимаюсь через Powershell. Очень удобно, когда нужен простенький GUI, например:


helloworldGui.ps1
$Assem = (
    “System.Windows.Forms”,
    "System.Drawing",
    "System.Core",
    "System.Data",
    "System.Xml"
    )
$Source = @”
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Infor.LMS.Utils.TranslationSearch
{

    public class Form1: Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(10, 10);
            this.label1.Name = "label1";
            this.label1.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);           
            this.label1.Size = new System.Drawing.Size(148, 13);
            this.label1.Text = "Hello world!";

            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(300, 200);
            this.Controls.Add(this.label1);
            this.Margin = new System.Windows.Forms.Padding(2);
            this.Name = "Form1";
            this.Text = "Hello World!";

            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label label1;

        //End of codegen

        public Form1()
        {
            InitializeComponent();
        }
    }

    public static class Program 
    {
        public static void Start()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        } 
    }
}
“@

Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp 

iex "[Infor.LMS.Utils.TranslationSearch.Program]::Start()"

более развитый инструмент предоставляет пакет DynamicExpresso
> для сериализации и десериализации лямбда-выражений

Главное не принимать от клиентской стороны лямбда выражения, иначе это готовый remote code execution

Да, вот для этого и искал, ограничение для доступных namespace-ов и reference-ов, но увы, не нашел. Можно у автора sharplab.io подсмотреть

С Microsoft.CodeAnalysis.CSharp.Scripting только одна проблема, если на .Net5 попытаться запаблишить как self-contained с флагом PublishSingleFile=true, то оно не работает (по крайней мере сейчас).

Спасибо за информацию!
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.