有没有一种方法可以使用 .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/