Существует ли способ динамично выполнить строку в .NET, подобном оценке () в JavaScript или динамическом sql в sql?

Я решил эту проблему, добавив настройки клонирования в конвейеры Bitbucket. Я не уверен, почему это работает, но я добавил это прежде, чтобы решить это, но удалил это некоторое время назад. Я снова начал получать эту проблему, поэтому добавление ее решило проблему. Но предупреждение состоит в том, что это может немного замедлить ваше развертывание, так как git сделает полный клон в контейнере конвейеров. Вот мой фрагмент конфигурации bitbucket-pipelines.yml. Это просто подталкивает к лазурному развертыванию git url. Добавление «глубина клона: полная» разрешает это для меня:

image: python:2.7.13

clone:
  depth: full

pipelines:

  branches:
    master:
      - step:
          script:
            - git push "https:/...
8
задан Rory 3 February 2009 в 19:57
поделиться

6 ответов

как другие уже упомянул не действительно возможный скомпилировать c# в оценке () функция. та функциональность настругана для последнего выпуска сброса, который anders продемонстрировал в PDC.

как другой solutionm, если Ваше приложение может работать моно, можно просто использовать его функцию оценки, которая может динамично скомпилировать код c#, точно так же, как JavaScript. это - basicly, уже делающий, что .NET сможет сделать через год или два.

как альтернатива при наклонении использования, моно, Вы могли бы записать часть, которая делает обработку строк в ironruby, который имеет оценку (). остальная часть Вашей привычки кода даже знает об использовании рубина для этого class/assambly.

ссылка Вы отправили во взглядах обновления, довольно сложных для такого простого варианта использования. использование ironruby все, что необходимо было бы сделать, записать MyDynamicEvalClass что-то вроде этого:

class MyDynamicEvalClass
  def eval(someString,transformString)
    eval(someString,transformString)
  end
end

и замена "ManipulationSetting" с некоторым кодом Ruby, который возвращает новую строку

1
ответ дан 5 December 2019 в 08:26
поделиться

Это не tooo трудно ;) Я соединил немного примера. Это должно помочь Вам решить, хотите ли Вы использовать динамические сценарии.. или regexes.

То, что можно сделать, создают интерфейс в блоке, который реализует динамический код:

namespace CompileScriptExample
{
  public interface IStringManipulator
  {
    string processString(string aString);
  }
}

Затем создайте класс ScriptRunner:

namespace CompileScriptExample
{ 
public class ScriptRunner
{

    public static string RunScript(string scriptCode, string scriptParameter)
    {

        CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();

        //configure parameters
        CompilerParameters parameters = new CompilerParameters();
        parameters.GenerateExecutable = false;
        parameters.GenerateInMemory = true;
        parameters.IncludeDebugInformation = false;
        string reference;
        // Set reference to current assembly - this reference is a hack for the example..
        reference = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        parameters.ReferencedAssemblies.Add(reference+"\\CompileScriptExample.exe");

        //compile
        CompilerResults results = provider.CompileAssemblyFromSource(parameters, new string[] { scriptCode });

        if (results.Errors.Count == 0)
        {
            IStringManipulator compiledScript=(IStringManipulator)FindInterface(results.CompiledAssembly, "IStringManipulator");
            return compiledScript.processString(scriptParameter);//run the script, pass the string param..
        }
        else
        {
            foreach(CompilerError anError in results.Errors)
            {
                MessageBox.Show(anError.ErrorText);
            }
            //handle compilation errors here
            //..use results.errors collection
            throw new Exception("Compilation error...");
        }
    }

    private static object FindInterface(Assembly anAssembly, string interfaceName)
    {
        // find our interface type..
        foreach (Type aType in anAssembly.GetTypes())
        {
            if (aType.GetInterface(interfaceName, true) != null)
                return anAssembly.CreateInstance(aType.FullName);
        }
        return null;
    }
}

}

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

string myScriptString=@"using CompileScriptExample;
public class MyStringManipulator : IStringManipulator
{
  public string processString(string aString)
  {
        return aString+aString;
  }
};

и затем.. в Вашем коде используйте ScriptRunner для обработки строки с динамическим кодом:

string processedString = ScriptRunner.RunScript(myScriptString, "hello");
13
ответ дан 5 December 2019 в 08:26
поделиться

Я знаю, что Вы после того, как C#, но код я имею для этого, находится в VB. Вы могли перевести его достаточно легко использование VB Fusion Разработчика к преобразователю C#. Я использовал его на проекте позволить пользователям добавлять сложные вычисления в свое приложение во времени выполнения. Это компилирует их код VB в библиотеку в памяти и затем выполняет код, возвращая получающийся вывод. Это могло повторно ставиться целью довольно легко для того, что Вы пытаетесь сделать.

Imports System.Reflection
Imports System.CodeDom.Compiler
Imports System.Text.RegularExpressions
Imports System.Math

Module Module1

  Function Evaluate(ByVal Expression As String, ByVal Args() As Object) As Object

    If Expression.Length > 0 Then

        'Replace each parameter in the calculation expression with the correct values
        Dim MatchStr = "{(\d+)}"
        Dim oMatches = Regex.Matches(Expression, MatchStr)
        If oMatches.Count > 0 Then
            Dim DistinctCount = (From m In oMatches _
                                 Select m.Value).Distinct.Count
            If DistinctCount = Args.Length Then
                For i = 0 To Args.Length - 1
                    Expression = Expression.Replace("{" & i & "}", Args(i))
                Next
            Else
                Throw New ArgumentException("Invalid number of parameters passed")
            End If
        End If

        Dim FuncName As String = "Eval" & Guid.NewGuid.ToString("N")
        Dim FuncString As String = "Imports System.Math" & vbCrLf & _
                                   "Namespace EvaluatorLibrary" & vbCrLf & _
                                   "  Class Evaluators" & vbCrLf & _
                                   "    Public Shared Function " & FuncName & "() As Double" & vbCrLf & _
                                   "      " & Expression & vbCrLf & _
                                   "    End Function" & vbCrLf & _
                                   "  End Class" & vbCrLf & _
                                   "End Namespace"

        'Tell the compiler what language was used
        Dim CodeProvider As CodeDomProvider = CodeDomProvider.CreateProvider("VB")

        'Set up our compiler options...
        Dim CompilerOptions As New CompilerParameters()
        With CompilerOptions
            .ReferencedAssemblies.Add("System.dll")
            .GenerateInMemory = True
            .TreatWarningsAsErrors = True
        End With

        'Compile the code that is to be evaluated
        Dim Results As CompilerResults = _
            CodeProvider.CompileAssemblyFromSource(CompilerOptions, FuncString)

        'Check there were no errors...
        If Results.Errors.Count > 0 Then
        Else
            'Run the code and return the value...
            Dim dynamicType As Type = Results.CompiledAssembly.GetType("EvaluatorLibrary.Evaluators")
            Dim methodInfo As MethodInfo = dynamicType.GetMethod(FuncName)
            Return methodInfo.Invoke(Nothing, Nothing)
        End If

    Else
        Return 0

    End If

    Return 0

  End Function

End Module

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

Dim Expr As String = "  If ({0} < 20000) Then" & vbCrLf & _
                     "    Return Max(15, Min(75,0.12*{0}))" & vbCrLf & _
                     "  Else" & vbCrLf & _
                     "    Return Max(75,0.05*{0})" & vbCrLf & _
                     "  End If"

И затем настроенный некоторые аргументы в пользу выражения и выполнитесь:

Dim Args As New List(Of String)
While True
    Dim Val As String = Console.ReadLine
    Args.Clear()
    If IsNumeric(Val) Then
        Args.Add(Val)
        Dim dblOut As Object = Evaluate(Expr, Args.ToArray)
        Console.WriteLine(dblOut)
    Else
        Exit While
    End If
End While
4
ответ дан 5 December 2019 в 08:26
поделиться

Я думаю, что это - возможное использование reflection.emit и codedom, чтобы сделать это, но это нисколько не тривиально, и я отговариваю от него.

Как альтернатива, Вы могли попытаться настроить строку формата, возможно в дополнение к regex.

1
ответ дан 5 December 2019 в 08:26
поделиться

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

Выяснение вывода легко в этом случае, у Вас есть строка. Для исходных данных казалось бы, что у Вас может быть переменное количество исходных данных. Это было бы определено как IEnumerable<string>.

Имея это в виду, можно определить интерфейс как так:

public interface IStringManipulation
{
  string Manipulate(IEnumerable<string> parameters);
}

Затем было бы легко определить реализации этого типа и затем поместить имена типов в Вашу конфигурацию.

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

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

0
ответ дан 5 December 2019 в 08:26
поделиться

Я просто натыкался на что-то на днях, которое делает просто это на другом языке.NET: http://reverseblade.blogspot.com/2009/02/dont-wait-for-c-5-use-nemerle.html

Я предположил бы, что Вы могли записать свой строковый код обработки в nemerle, скомпилировать, и ссылка от Вашего C# или приложения VB.

Я все еще одобрил бы расширяемый дизайн как casperOne, предлагает. Путем выполнения динамических сценариев Вы будете просто продвигать компиляцию в приложение, и развертывание в любой процесс получает строки программирования к приложению. Но это кажется, что у Вас есть свои причины, таким образом, единственной другой вещью, которую я рассмотрел бы здесь, является безопасность. Идеально, Вы хотите ограничить пользователя как можно больше только к управлению строками, в этом случае List-of-Regex походит на довольно хороший вариант.

0
ответ дан 5 December 2019 в 08:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: