c# - 有没有办法在 .net 中动态执行字符串,类似于 javascript 中的 eval() 或 sql 中的动态 sql?

标签 c# .net string dynamic

有没有一种方法可以使用 .net 2.0 以类似于 javascript 中的 eval() 或在 tsql 中使用 sp_executeSQL 的方式动态执行包含在字符串中的代码?

我在一个变量中有一个字符串值,我想在我的应用程序中的某个时刻对其进行操作 - 因此代码本质上是字符串操作。我不知道需要什么不同的操作,所以我希望它们是可配置的。

我真的不在乎动态代码是用什么语言编写的,只要是最容易实现和编写起来足够简单的语言。

例如,我可能想替换“.”的实例带有“-”的字符,或去掉所有空格,或类似的。如果我在 sql 中执行此操作,我会使用动态 sql,但我想在 .net 代码中执行它,如下所示:

// Get the value to be manipulated
string s = ... // wherever s comes from

// Get the manipulation code, eg this might come from a database 
// setting that can be changed without recompiling the .net code.
string manipulation = Settings.GetSomeValue("ManipulationSetting");

// This is what I want to know how to do: apply some manipulation to the string.
string result = MagicDynamicEvalClass.Eval(manipulation, s);

// Now I would do stuff with the result.

我可能只使用正则表达式查找/替换表达式。由于我所做的只是字符串操作,只要我可以编写足够聪明的正则表达式,这就足够了。例如:

// Get the value to be manipulated
string s = ... // wherever s comes from

// Get the code to use to manipulate s, eg this might come from a database 
// setting that can be changed without recompiling the .net code.
string findRegex = Settings.GetSomeValue("RegexPattern");
string replaceRegex = Settings.GetSomeValue("RegexReplace");

// This is what I want to know how to do: apply some manipulation to the string.
string result = Regex.Replace(s, findRegex, replaceRegex);

// Now I can do stuff with the result.

但在某些情况下,我的操作要求可能会超出使用正则表达式的可能性,或者我可能想要应用多个步骤,例如替换“.”。带'-' 和带空格。或许我可以存储一个查找/替换正则表达式列表并遍历它们……但是有人有更好的建议吗?

更新 - 使用动态 sql 的示例

我不想要一个要求我提前知道可以进行哪些操作的解决方案,我真的在寻找一些简单的东西。例如在 sql 中我会做这样的事情:

declare @s nvarchar(1000)
declare @manipulation nvarchar(1000)
declare @result nvarchar(1000)

-- ... Get the values from wherever they come from

-- Execute the manipulation dynamically
EXEC sp_ExecuteSQL @stmt = @manipulation
    , @params = N'@s nvarchar(1000), @result nvarchar(1000) OUTPUT'
    , @s = @s, @result = @result OUTPUT

然后我可以将任意 sql 放入我的@manipulation,就像这样 SET @result = REPLACE( REPLACE( @s, '.', '-'), ' ', '' )

是的,这需要我小心允许将哪些值放入@manipulation,但它会给我 future 所需的灵 active 。

我想在 javascript 中也可以使用类似的方法,使用 eval()。

更新 - 使用 .net 中的 MSScript 控件的示例:

This似乎是一种可能的方法,尽管对于我要处理的简单案例来说可能有点矫枉过正。它使用 Microsoft Script Control 库来允许执行任意 VBScript。

最佳答案

这并不难;) 我举了一个小例子。 这应该可以帮助您决定是要使用动态脚本..还是正则表达式。

您可以做的是在您的程序集中创建一个接口(interface),您的动态代码将实现该接口(interface):

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

关于c# - 有没有办法在 .net 中动态执行字符串,类似于 javascript 中的 eval() 或 sql 中的动态 sql?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/508213/

相关文章:

c# - 如何从远程 url 获取有效的文件名和扩展名以保存它。?

c# - 按多个键值对数组进行排序

c# - 通过静态对象的静态属性访问 asp.net session 变量是否安全?

c# - 哪个 nuget 包包含 Nuget 中的 Microsoft.WindowsAzure.StorageClient.dll

c++ - 包含 '\0' 的字符串文字 - 为什么它们不一样?

javascript - 从字符串中提取唯一字符并保留字符串之间的空格

c# - WCF 服务在单个线程中处理传入请求,尽管有 ConcurrencyMode.Multiple

c# - 部分 MonthCalendar 本地化失败 ('Today' 标签未翻译)

c# - 如何将 Windows TaskScheduler RunDurationFor 更改为无限期

java - R.java 不在 Android 中保存 Id