Невозможно передать объект типа "System.Linq.Expressions.UnaryExpression" для ввода "System.Linq.Expressions.MemberExpression"
Я создал метод в С#, чтобы получить имя метода
public string GetCorrectPropertyName<T>(Expression<Func<T, string>> expression)
{
return ((MemberExpression)expression.Body).Member.Name; // Failure Point
}
и называя его
string lcl_name = false;
public string Name
{
get { return lcl_name ; }
set
{
lcl_name = value;
OnPropertyChanged(GetCorrectPropertyName<ThisClassName>(x => x.Name));
}
}
Это отлично работает, если свойство является строкой, и для всех остальных типов это исключение:
Невозможно передать объект типа "System.Linq.Expressions.UnaryExpression" для ввода "System.Linq.Expressions.MemberExpression".
- Я изменил строку на объект в сигнатуре метода, но потом снова сработал.
- Я изменил вызов с
x => x.PropertyName
на x => Convert.ToString(x.PropertyName)
, и он все еще не работает
Где я ошибаюсь?
Ответы
Ответ 1
Вам нужна отдельная строка для извлечения члена, где входное выражение является Унарным выражением.
Просто изменил это из VB.Net, так что может быть немного отключен - сообщите мне, нужно ли мне делать какие-либо незначительные изменения:
public string GetCorrectPropertyName<T>(Expression<Func<T, Object>> expression)
{
if (expression.Body is MemberExpression) {
return ((MemberExpression)expression.Body).Member.Name;
}
else {
var op = ((UnaryExpression)expression.Body).Operand;
return ((MemberExpression)op).Member.Name;
}
}
Версия VB:
Public Shared Function GetCorrectPropertyName(Of T) _
(ByVal expression As Expression(Of Func(Of T, Object))) As String
If TypeOf expression.Body Is MemberExpression Then
Return DirectCast(expression.Body, MemberExpression).Member.Name
Else
Dim op = (CType(expression.Body, UnaryExpression).Operand)
Return DirectCast(op, MemberExpression).Member.Name
End If
End Function
Обратите внимание, что входное выражение не возвращает строку обязательно - это ограничивает только чтение свойств, возвращающих строки.
Ответ 2
Это очевидно, связанный с боксом/распаковкой. Лямбда-выражения, возвращающие типы значений, которые требуют бокса, будут представлены как UnaryExpressions, тогда как те, которые возвращают ссылочные типы, будут представлены как MemberExpressions.
Ответ 3
После того, как я задал этот вопрос (да, я ОП), я получил комментарии по вопросу от Jon
и я придумал этот
public string ResolvePropertyName<TEntity>(Expression<Func<TEntity>> expression)
{
try {
if (expression == null) {
Throw New ArgumentNullException("propertyExpression")
}
object memberExpression = expression.Body as MemberExpression;
if (memberExpression == null) {
Throw New ArgumentException("The expression is not a member access expression.", "propertyExpression")
}
object property = memberExpression.Member as PropertyInfo;
if (property == null) {
Throw New ArgumentException("The member access expression does not access a property.", "propertyExpression")
}
object getMethod = property.GetGetMethod(true);
if (getMethod.IsStatic) {
Throw New ArgumentException("The referenced property is a static property.", "propertyExpression")
}
return memberExpression.Member.Name;
} catch (Exception ex) {
return string.Empty;
}
}