I'm trying use expressions in order to have strong typing over properties.
So I have this model.
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
And this method which should, well in the end I would like to use the properties in some way but for now I just want to return them.
public List<string> DoSomething<TEntity>(params Expression<Func<TEntity, object>>[] expressions)
{
List<string> props = new List<string>();
foreach (var expression in expressions)
{
var memberExpression = expression.Body as MemberExpression;
var q = memberExpression.Member.Name;
props.Add(q);
}
return props;
}
This is the usage
var props = DoSomething<Entity>(x => x.Id, x => x.Name);
Well, It works but only partially. What I mean by that is that it will work for reference types, for example it will work for Name property because it is a reference type, but it will return null for any value type, in this case for ID which is an int.
Why is that and what is the solution?
Expression<Func<TEntity, object>>
is an Expression that builds a Func which returns an object
(which is a reference type). If you pass x => x.Id
as value of that Expression, the return type of the resulting Func will not match, as int
is a value type but the Func is expected to return a reference type.
C#'s compiler will see that and automatically build a Func that wraps the int
inside an object
(called boxing). But that Func no longer has a simple MemberExpression as its body, because the MemberExpression has to be wrapped in a "boxing expression".
That's basically what happens. So you have to handle the case where expression.Body
is not of type MemberExpression
to fix that.
This is untested, but it might help:
if (!(expression.Body is MemberExpression))
{
if (expression.Body is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.TypeAs)
expression = unaryExpression.Operand as MemberExpression;
else
expression = null;
if (expression == null)
throw new ArgumentException("something happened");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.