ExpressionParser failed to parse Func type
I was trying to parse a expression string like this:
ParameterExpression p1 = Expression.Parameter(typeof(Customer), "p1");
ParsingConfig config = new ParsingConfig();
config.CustomTypeProvider = new FuncTypeProvider();
var e3 = DynamicExpressionParser.ParseLambda(/*config,*/ new ParameterExpression[] { p1 }, typeof(Func<int, bool>), "(p1.Method()).Invoke(1)");
var result = e3.Compile().DynamicInvoke(new Customer());
And the Customer class looks like this:
public class Customer
{
public Func<int, bool> Method()
{
return x=>x>0;
}
}
FuncTypeProvider is implemented like this:
public class FuncTypeProvider : IDynamicLinkCustomTypeProvider
{
private HashSet<Type> _customTypes;
public HashSet<Type> GetCustomTypes()
{
if (_customTypes != null)
return _customTypes;
_customTypes = new HashSet<Type>();
_customTypes.Add(typeof(Func<int, bool>));
return _customTypes;
}
public Dictionary<Type, List<MethodInfo>> GetExtensionMethods()
{
throw new NotImplementedException();
}
public Type ResolveType(string typeName)
{
throw new NotImplementedException();
}
public Type ResolveTypeBySimpleName(string simpleTypeName)
{
throw new NotImplementedException();
}
}
Exception occurs when creating e3:
System.Linq.Dynamic.Core.Exceptions.ParseException: 'Expression of type 'Func`2' expected'
Stack trace:
at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor)
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Type delegateType, ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values)
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values)
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, ParameterExpression[] parameters, Type resultType, String expression, Object[] values)
Is it because I missed something that should be configured before parsing? Or is it because the lib cannot process a Func type return?
I'm quite a noob here, if there's anything wrong with my expression or the way I express, please let me know. Any help would be appreciated.
- The issue is that you are supposed to pass the return type of the lambda but not the lambda itself into the "resultType" parameter.
- Consider deriving from DefaultDynamicLinqCustomTypeProvider rather than implementing the interface.
[Test]
public void Issue570()
{
var p1 = Expression.Parameter(typeof(Customer), "p1");
var config = new ParsingConfig
{
CustomTypeProvider = new FuncTypeProvider()
};
var lambda = DynamicExpressionParser.ParseLambda(config, new[] { p1 }, typeof(bool), "p1.Method().Invoke(1)");
var compiledLambda = lambda.Compile();
//Actually, you don't need dynamic invoke since the lambda is parsed
//and you know the actual type of your delegate
var staticInvoke = ((Func<Customer, bool>)compiledLambda)(new Customer());
TestContext.WriteLine($"Static invoke: {staticInvoke}");
//But if, however, you want dynamic invoke it works as well
var dynamicInvoke = compiledLambda.DynamicInvoke(new Customer());
TestContext.WriteLine($"Dymamic invoke: {dynamicInvoke}");
}
public class Customer
{
public Func<int, bool> Method()
{
return x => x > 0;
}
}
//Consider deriving form DefaultDynamicLinqCustomTypeProvider rather than implementing the interface
public class FuncTypeProvider : DefaultDynamicLinqCustomTypeProvider
{
public override HashSet<Type> GetCustomTypes()
{
var customTypes = base.GetCustomTypes();
customTypes.Add(typeof(Func<int, bool>));
return customTypes;
}
}
Hello, @ademchenko
Thank you so much for helping.
I literally confused the "returnType" of p1.Method with p1.Method.Invoke.