Expression of type 'System.Int32' cannot be used for return type 'System.Object'
Have you tried using Expression.Convert? That will add the boxing/lifting/etc conversion.
Expression conversion = Expression.Convert(expression, typeof(object));
func = Expression.Lambda<Func<T, Object>>(conversion, parameterExpression).Compile();
Convert ExpressionFuncTDocument, object to ExpressionFuncTDocument, TOutput
You just need to wrap the original expression's Body
in a Convert
expression and then rebuild your lambda. Here's how I would do it if I could use generics:
Expression<Func<TInput, TReturn>> ConvertReturnValue<TInput, TReturn>(
Expression<Func<TInput, object>> inputExpression)
{
Expression convertedExpressionBody = Expression.Convert(
inputExpression.Body, typeof(TReturn)
);
return Expression.Lambda<Func<TInput, TReturn>>(
convertedExpressionBody, inputExpression.Parameters
);
}
Usage:
Expression<Func<TDocument, object>> inputExpression = d => d.Name;
Expression<Func<TDocument, string>> convertedExpression
= ConvertReturnValue<TDocument, string>(inputExpression);
// Test.
TDocument doc = new TDocument { Name = "Zzz" };
string name = convertedExpression.Compile().Invoke(doc);
Assert.Equal("Zzz", name);
No generics
If you cannot use generics because you don't know the return type at compile time, Expression.Lambda
actually offers a non-generic overload, which you can use like this:
Expression ConvertReturnValue<TInput>(Expression<Func<TInput, object>> inputExpression, Type returnType)
{
Expression convertedExpressionBody = Expression.Convert(inputExpression.Body, returnType);
return Expression.Lambda(convertedExpressionBody, inputExpression.Parameters);
}
The above still returns an Expression<Func<TInput, TReturn>>
(upcast to a non-generic Expression
). You can downcast it later if you need to:
Expression<Func<TDocument, object>> inputExpression = d => d.Name;
Expression<Func<TDocument, string>> convertedExpression
= (Expression<Func<TDocument, string>>)ConvertReturnValue(inputExpression, typeof(string));
// Test.
TDocument doc = new TDocument { Name = "Zzz" };
string name = convertedExpression.Compile().Invoke(doc);
Assert.Equal("Zzz", name);
Addendum
Note that for struct return types, the final expression may end up looking like this:
(TDocument d) => (int)(object)d.ID;
Expression of type 'System.Int64' cannot be used for return type 'System.Object'
Depending on how you use result
you could create it dynamically with the delegate type Func<Entity, long>
and type it as a LambdaExpression
:
ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e");
Expression propertyAccess = Expression.Property(entityParameter, property);
var funcType = typeof(Func<,>).MakeGenericType(typeof(Entity), property.PropertyType);
LambdaExpression result = Expression.Lambda(funcType, propertyAccess, entityParameter);
Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)'
EDIT
Found the solution in this question. You need to convert the expression to Object
before calling the Equals(object)
method:
var converted = Expression.Convert(searchExpression, typeof(object));
body = Expression.Call(propertyExpression, containsMethod, converted);
Nicodemus13's suggestion of explicitly setting searchExpression
's type to Object
in the first place should work, too.
Original
I haven't found the issue yet, but I have reproduced the problem in a SSCCE using Linqpad:
void Main()
{
var myInstance = new myClass();
var equalsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });
int? nullableInt = 1;
var nullableIntExpr = System.Linq.Expressions.Expression.Constant(nullableInt);
var myInstanceExpr = System.Linq.Expressions.Expression.Constant(myInstance);
var propertyExpr = System.Linq.Expressions.Expression.Property(myInstanceExpr, "MyProperty");
var result = Expression.Call(propertyExpr,equalsMethod,nullableIntExpr); // This line throws the exception.
Console.WriteLine(result);
}
class myClass{public int? MyProperty{get;set;}}
This line:
containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });
returns a MethodInfo
for the method Int32?.Equals (Object other)
. Notice the parameter type is object
, not Int32
(or Int32?
) as you might expect.
The reason is typeof(Int32?)
is System.Nullable<Int32>
, which only has the Equals(object)
method.
Expression of type 'System.Int16' cannot be used for return type 'System.Object'
The problem here is that <Tprop>
is not of the Type Int16
and the string you are passing which is a columnname of the type Int16
You can simply specify the <Tprop>
wherever you are calling the function SelectAdmin<TProp>
.
for example:
`SelectAdmin<int>(.......your parameters here);`
if the sSortExpression is of the Type int16.
If it is of the type DateTime
you can call like this
SelectAdmin<DateTime>(.......your parameters here);
Expression of type 'System.DateTime' cannot be used for return type 'System.Object'
Just add a conversion in there:
Expression<Func<MyEntity, object>> sortExpression =
Expression.Lambda<Func<AMyEntity, object>>(
Expression.Convert(
Expression.Property(param, sortKey),
typeof(object)),
param);
Expression of type 'System.Func`2[T,System.Boolean]' cannot be used for return type 'System.Boolean'
Not sure what the serializedText
is in your snippet, but as long as it is a LambdaExpression
which returns a boolean
you should be able to do the below.
Expression expression = Expression.Lambda(Expression.Constant(true), Expression.Parameter(typeof(string)));
Expression<Func<string, bool>> typedExpression = (Expression<Func<string, bool>>)(expression);
Console.WriteLine(typedExpression.Compile().Invoke("Hello"));
replace string
with your generic type.
In your example, if the serializedText
can be deserialized into a Expression
the below should work, you would have to change it for your considerations.
Expression<Func<T, bool>> typedExpression = (Expression<Func<T, bool>>)Expression.Lambda(
serializer.DeserializeText(serializedText),
Expression.Parameter(typeof(T)));
Building a Linq sort expression from string results in 'Expression of system.int32 can not be used for return type System.Object '
It seems like this is ultimately a minor mistake.
- You're trying to order by the
Expression<Func<T, object>>
(as in the value of that, not the value ofrandomNumber
determines the sort order. .OrderBy
for enumerables (not queryables) expects aFunc<TSource, TKey>
whereTSource
isOrderEntity
andTKey
is supposed to be yourobject
value in this case.
So we need to do two things:
- Compile the expression.
- Use it for sorting.
Essentially we need this
Func<OrderEntity, object> sortAccessor = ToLambda<OrderEntity>(propertyForExpression).Compile();
var sortedOrders = orders.OrderBy(sortAccessor);
or
Func<OrderEntity, object> sortAccessor = ToLambda<OrderEntity>(propertyForExpression).Compile();
var sortedOrders = orders.OrderBy(x => sortAccessor(x));
or
var sortedOrders = orders.OrderBy(x => ToLambda<OrderEntity>(propertyForExpression).Compile()(x));
or
var sortedOrders = orders.OrderBy(ToLambda<OrderEntity>(propertyForExpression).Compile());
You could also change the method to return the compiled Func<T, object>
instead:
static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{
var propertyNames = propertyName.Split('.');
var parameter = Expression.Parameter(typeof(T));
Expression body = parameter;
foreach (var propName in propertyNames)
body = Expression.Property(body, propName);
var convertedResult = Expression.Convert(body, typeof(object));
var func = Expression.Lambda<Func<T, object>>(convertedResult, parameter);
return func;
}
and then use it more like this:
Func<OrderEntity, object> sortAccessor = ToLambda<OrderEntity>(propertyForExpression);
var sortedOrders = orders.OrderBy(sortAccessor);
or this:
var sortedOrders = orders.OrderBy(ToLambda<OrderEntity>(propertyForExpression));
Note: the reason I'm suggesting compiling the expression outside of the loop and caching it as a Func<OrderEntity, object>
variable is because otherwise it will be evaluated multiple times for a single .OrderBy
.
Related Topics
C# MACro Definitions in Preprocessor
Accessing UI Controls in Task.Run with Async/Await on Winforms
Serialization Breaks in .Net 4.5
C# Property and Ref Parameter, Why No Sugar
How to Get Character for a Given Ascii Value
Why Generic Ilist<> Does Not Inherit Non-Generic Ilist
Where Are Clr-Defined Methods Like [Delegate].Begininvoke Documented
How to Change My New List Without Changing the Original List
How to Set a Proxy for Webbrowser Control Without Effecting the System/Ie Proxy
Image.Fromstream() Method Returns Invalid Argument Exception
Thread with Multiple Parameters
How to Draw a Rounded Rectangle with Winforms (.Net)
Return All Enumerables with Yield Return at Once; Without Looping Through
Detecting If Paste Event Occurred Inside a Rich Text Box
Opening a "Known File Type" into Running Instance of Custom App - .Net