Using ParseLambda to calculate score


  • I have to calculate a score value for different groups of users, and each group has a different scoring mechanism.  I'm trying to use ParseLambda to calculate the score. 

    My code runs perfectly when I access the property MyVals.Val3 as I do in the code below.  However, my user groups have uniquely named scoring items in the array or collection (Group 1 may have items Val1/Val2/Val3, Group 1 may have items Val4/Val5/Val6).  When I alter my xml to access the method MyVals.Val(@0) instead of property MyVals.Val3, I get the error Methods on type 'MyVals' are not accessible on the call to ParseLambda.

    Is there any way to access a method of an object when using ParseLambda or am I just missing something?  Thanks in advance!

    using System;
    using System.Linq;
    using System.Xml.Serialization;
    using System.IO;
    using System.Linq.Expressions;
    using System.Windows.Forms;
    namespace ConsoleApplication1
    	public class provider
    		public string expression { get; set; }
    	public class MyVals
    		private double[] _vals = { 0, 1, 3, 5 };
    		public double Val(int index) { return _vals[index]; }
    		public double Val1 { get { return _vals[1]; } }
    		public double Val2 { get { return _vals[2]; } }
    		public double Val3 { get { return _vals[3]; } }
    	public class Program
    		static void Main(string[] args)
    			var xml =
    				"<provider>" +
    				"	<expression>" +
    				"		MyVals.Val3" +
    				"	</expression>" +
    			var serializer = new XmlSerializer(typeof(provider));
    			var provider = (provider)serializer.Deserialize(new StringReader(xml));
    			var parameter = Expression.Parameter(typeof(MyVals), "MyVals");
    			var lambda = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter }, typeof(double), provider.expression, 3);
    			var myVals = new MyVals();
    			var result = (double)lambda.Compile().DynamicInvoke(myVals);
    			MessageBox.Show(result.ToString(), "Result");

    3 มีนาคม 2555 4:54



  • Hi bobertkuekn,

    I test your code, it works! You should add Dynamic.cs in your project for DynamicExpression.ParseLambda method

    public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values) {
                ExpressionParser parser = new ExpressionParser(parameters, expression, values);
                return Expression.Lambda(parser.Parse(resultType), parameters);
    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • ทำเครื่องหมายเป็นคำตอบโดย Alan_chenModerator 13 มีนาคม 2555 22:33
    5 มีนาคม 2555 7:32
  • Thanks for the response, Alan!  I was actually already referencing System.Linq.Dynamic,.  I removed the reference and added the Dynamic.cs to my project.  My code still seems to fail in the ParseMemberAccess routine because it's calling the IsPredefinedType routine and class "MyVals" is not a predefined type.  Here's the call stack:

    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseMemberAccess(System.Type type = {Name = "MyVals" FullName = "ConsoleApplication1.MyVals"}, System.Linq.Expressions.Expression instance = {System.Linq.Expressions.TypedParameterExpression}) Line 1276	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParsePrimary() Line 947 + 0xd bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseUnary() Line 936 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseMultiplicative() Line 883 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseAdditive() Line 853 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseComparison() Line 770 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseLogicalAnd() Line 755 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseLogicalOr() Line 740 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.ParseExpression() Line 724 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.ExpressionParser.Parse(System.Type resultType = {Name = "Double" FullName = "System.Double"}) Line 686 + 0x8 bytes	C#
    dynamiclinq.exe!System.Linq.Dynamic.DynamicExpression.ParseLambda(System.Linq.Expressions.ParameterExpression[] parameters = {System.Linq.Expressions.ParameterExpression[1]}, System.Type resultType = {Name = "Double" FullName = "System.Double"}, string expression = "x.Val(@0)", object[] values = {object[1]}) Line 185 + 0xd bytes	C#
    dynamiclinq.exe!ConsoleApplication1.Program.Main(string[] args = {string[0]}) Line 43 + 0xd9 bytes	C#

    Any help you can give would be appreciated!

    12 มีนาคม 2555 18:28
  • I should've mentioned it yesterday, but I got Dynamic.cs from a link in the Scott Gu archive you referenced:

    Thanks in advance for the help!

    • ทำเครื่องหมายเป็นคำตอบโดย Alan_chenModerator 13 มีนาคม 2555 22:33
    13 มีนาคม 2555 17:55