回答
這是可能的,是的。您必須解析字符串,例如,使用表達式樹編譯委託。
以下是創建(x, y, z) => x + y * z
使用表達式樹的例子:
ParameterExpression parameterX = Expression.Parameter(typeof(int), "x");
ParameterExpression parameterY = Expression.Parameter(typeof(int), "y");
ParameterExpression parameterZ = Expression.Parameter(typeof(int), "z");
Expression multiplyYZ = Expression.Multiply(parameterY, parameterZ);
Expression addXMultiplyYZ = Expression.Add(parameterX, multiplyYZ);
Func<int,int,int,int> f = Expression.Lambda<Func<int, int, int, int>>
(
addXMultiplyYZ,
parameterX,
parameterY,
parameterZ
).Compile();
Console.WriteLine(f(24, 6, 3)); // prints 42 to the console
+1這是一個很好的例子,但它是針對有問題的字符串量身定製的。這個例子不會幫助OP分析一個隨機字符串,推斷字符串中標識符的類型,並根據找到的內容創建一個方法。儘管如此,對你來說,+1是一個很好的例子。 – 2009-10-15 20:46:14
+1,這裏是9999不再! – 2009-10-15 20:56:44
我認爲解析將比表達式樹更熟悉(至少解析文獻更大)OP。表達樹的目的僅僅是向他展示技術並展示他們的力量,而不是解決一般問題。 – jason 2009-10-15 21:01:12
C#沒有像這樣的功能(其他語言 - 如JavaScript - 有eval
函數來處理這樣的東西)。您將需要解析字符串並使用表達式樹或發佈IL自己創建一個方法。
這可能是可能的語法(例如ANTLR)和其產生表達式樹的解釋器。這不是一項小任務,但是,如果您限制接受的輸入範圍,則可以取得成功。下面是一些參考:
- C# ANTLR3 Grammar(複雜的,但你可以提取部分)
- Expression Trees
下面是一些代碼可能看起來像變換的ANTLR ITree成一個表達式樹。它並不完整,但會向你展示你的目標。
private Dictionary<string, ParameterExpression> variables
= new Dictionary<string, ParameterExpression>();
public Expression Visit(ITree tree)
{
switch(tree.Type)
{
case MyParser.NUMBER_LITERAL:
{
float value;
var literal = tree.GetChild(0).Text;
if (!Single.TryParse(literal, out value))
throw new MyParserException("Invalid number literal");
return Expression.Constant(value);
}
case MyParser.IDENTIFIER:
{
var ident = tree.GetChild(0).Text;
if (!this.variables.ContainsKey(ident))
{
this.variables.Add(ident,
Expression.Parameter(typeof(float), ident));
}
return this.variables[ident];
}
case MyParser.ADD_EXPR:
return Expression.Add(Visit(tree.GetChild(0)), Visit(tree.GetChild(1)));
// ... more here
}
}
在.Net框架中有這樣的功能。
這並不容易。您需要在語句中添加一些代碼,使其成爲一個完整的程序集,包括可以調用的類和方法。
之後,你使用的CodeDOM將字符串傳遞到
CSharpCodeProvider.CompileAssemblyFromSource(options, yourcode);
隨着搞清楚需要什麼參數,等等,以便與CompileAssemblyFromSource友好相處。 – user7116 2009-10-15 20:56:34
只是爲了好玩(任何有效的C#代碼字符串中允許的,只要它存在於mscorlib程序(沒有支票在所有錯誤):
static class Program
{
static string code = @"
public static class __CompiledExpr__
{{
public static {0} Run({1})
{{
return {2};
}}
}}
";
static MethodInfo ToMethod(string expr, Type[] argTypes, string[] argNames, Type resultType)
{
StringBuilder argString = new StringBuilder();
for (int i = 0; i < argTypes.Length; i++)
{
if (i != 0) argString.Append(", ");
argString.AppendFormat("{0} {1}", argTypes[i].FullName, argNames[i]);
}
string finalCode = string.Format(code, resultType != null ? resultType.FullName : "void",
argString, expr);
var parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("mscorlib.dll");
parameters.ReferencedAssemblies.Add(Path.GetFileName(Assembly.GetExecutingAssembly().Location));
parameters.GenerateInMemory = true;
var c = new CSharpCodeProvider();
CompilerResults results = c.CompileAssemblyFromSource(parameters, finalCode);
var asm = results.CompiledAssembly;
var compiledType = asm.GetType("__CompiledExpr__");
return compiledType.GetMethod("Run");
}
static Action ToAction(this string expr)
{
var method = ToMethod(expr, new Type[0], new string[0], null);
return() => method.Invoke(null, new object[0]);
}
static Func<TResult> ToFunc<TResult>(this string expr)
{
var method = ToMethod(expr, new Type[0], new string[0], typeof(TResult));
return() => (TResult)method.Invoke(null, new object[0]);
}
static Func<T, TResult> ToFunc<T, TResult>(this string expr, string arg1Name)
{
var method = ToMethod(expr, new Type[] { typeof(T) }, new string[] { arg1Name }, typeof(TResult));
return (T arg1) => (TResult)method.Invoke(null, new object[] { arg1 });
}
static Func<T1, T2, TResult> ToFunc<T1, T2, TResult>(this string expr, string arg1Name, string arg2Name)
{
var method = ToMethod(expr, new Type[] { typeof(T1), typeof(T2) },
new string[] { arg1Name, arg2Name }, typeof(TResult));
return (T1 arg1, T2 arg2) => (TResult)method.Invoke(null, new object[] { arg1, arg2 });
}
static Func<T1, T2, T3, TResult> ToFunc<T1, T2, T3, TResult>(this string expr, string arg1Name, string arg2Name, string arg3Name)
{
var method = ToMethod(expr, new Type[] { typeof(T1), typeof(T2), typeof(T3) },
new string[] { arg1Name, arg2Name, arg3Name }, typeof(TResult));
return (T1 arg1, T2 arg2, T3 arg3) => (TResult)method.Invoke(null, new object[] { arg1, arg2, arg3 });
}
static void Main(string[] args)
{
var f = "x + y * z".ToFunc<int, int, long, long>("x", "y", "z");
var x = f(3, 6, 8);
}
}
- 1. 從字符串創建匿名類型
- 2. 從字符串創建Java方法?
- 3. 從C中的字符串數組創建字符串
- 4. 從字符串中創建對象(C++)
- 5. 在C中創建字符串的方法有什麼區別?
- 6. 從字符串數組中創建一個字符串。最快的方法?
- 7. 創建的HtmlHelper方法在字符串
- 8. 要創建的字符串POST方法
- 9. 建立字符串的方法c
- 10. 從字符串創建對象名稱
- 11. 從字符串類名創建對象
- 12. 從列表中創建字符串的有效方法
- 13. C:從分隔的源字符串創建字符串數組
- 14. Noob,創建字符串方法的索引和子字符串
- 15. 創建我自己的字符串類/子字符串方法
- 16. 如何調用從匿名方法創建的MethodInfo?
- 17. 如何用字符串的名稱創建一個類方法?
- 18. C++從字符串創建ambigram
- 19. C#創建模式從字符串
- 20. C中的遞歸和匿名方法#
- 21. C#中的簡單匿名方法
- 22. 什麼是C#中的匿名方法?
- 23. C#2中的代表/匿名方法
- 24. 從列表/ SortedLists C#中創建CSV字符串的有效方法?
- 25. 創建方法和更新字符串
- 26. 匿名類型的反序列化json從字符串到DataContract的方法
- 27. 有沒有一種簡單的方法從C中的字符串數組創建一個字符串?
- 28. C++:創建字符串
- 29. 從字符串中創建列表的名字
- 30. 如何從TRttiMethod獲取/創建匿名方法?
我敢肯定有些傢伙在微軟做了一個關於.NET 4有編譯器可以作爲一個服務來完成這樣的事情廣播不知道,如果它是你的。情況雖然。 – 2009-10-15 20:57:47
當他在PDC討論「編譯器即服務」時,Anders正在談論非常遙遠的工作。 C#4肯定沒有這樣的工作。 – 2009-10-15 22:05:36
Duplicate:http://stackoverflow.com/questions/1437964/best-and-shortest-way-to-evaluate-mathematical-expressions/ 這個問題也比這個更具體回答。 – Joren 2009-10-19 10:40:41