Soru 'System.Linq.Expressions.MemberExpression' yazmak için 'System.Linq.Expressions.UnaryExpression' türünde nesne dönüştürülemiyor


Ben oluşturdum C # yöntemi methodname almak için

public string GetCorrectPropertyName<T>(Expression<Func<T, string>> expression)
{
   return ((MemberExpression)expression.Body).Member.Name; // Failure Point
}

ve onu

string lcl_name = false;
public string Name
{
get { return lcl_name ; }
set 
    {
        lcl_name = value;
        OnPropertyChanged(GetCorrectPropertyName<ThisClassName>(x => x.Name));
}
}

Bu özellik, özellik dize ve diğer tüm türleri için bu istisna verirse iyi çalışır:

'System.Linq.Expressions.MemberExpression' yazmak için 'System.Linq.Expressions.UnaryExpression' türünde nesne açılamıyor.

  1. Yöntem imzasında nesneyi dizgeye dönüştürdüm, ancak yine başarısız oluyor.
  2. Aramayı değiştirdim x => x.PropertyName için x => Convert.ToString(x.PropertyName) ve hala başarısız oluyor

Nerede yanlışım?


32
2017-09-14 08:09


Menşei


IMO, yardımcının bir alması gereken bir varyasyon kullanmak daha iyidir. Expression<Func<T>>. Bu, çağrı sitesi sözdizimini değiştirir GetCorrectPropertyName(() => this.Name)Benim görüşüme göre hem yazım için daha iyi (jenerik tip parametresi vermeye gerek yok) ve daha iyi okumak için (this.Name Niyeti çok iyi iletir). - Jon
@Jon: Buddy cevabınızı eklemekte çekinmeyin. Mevcut cevaptan daha iyi olursa, kesinlikle kabul edeceğim. - Nikhil Agrawal
Bunu yapmak istemezdim çünkü sorunun amacını gasp ederdi. Ancak bunun için kolayca kodu alabilirsiniz. İşteMicrosoft, bunu tam olarak Prism'de yapıyor. - Jon
Prizma 2'de (ya da bunun için tamamen Prism dışında) bunu yapmanı engelleyen hiçbir şey yoktur. - Jon
@ Jon: Ama bu yöntem (prizma) sadece özelliklerle sınırlı olmaz mı yoksa yöntemlere de uygulanabilir mi? - Nikhil Agrawal


Cevaplar:


Giriş ifadesinin bir Unary İfadesi olduğu Üye'yi ayıklamak için ayrı bir satıra ihtiyacınız vardır.

Sadece bunu VB.Net'den dönüştürdüm, bu yüzden biraz kapalı olabilir - küçük bir ayar yapmam gerekirse bana bildirin:

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 sürümü:

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

Girdi ifadesinin zorunlu olarak dizgi döndürmediğine dikkat edin; yalnızca dizeleri döndüren özellikleri okumakla sınırlar.


47
2017-09-14 08:19



Birisi, bunun gibi bir şeyin BCL'ye veya bir uzantıya henüz dahil edilmediğini merak ediyor. İnanılmaz derecede faydalı. - BoltClock♦
Sadece özellikleri ve yöntemleri (VB.Net'in Alt ve İşlevleri) için nasıl kullanılacağını / aradığını bilmek istedim? - Nikhil Agrawal
@NikhilAgrawal: Yeni bir soru sormak, buna bir atıfta bulunmak ve isteklerinizi tam olarak açıklamak en iyisidir. - Jon Egerton
Özellik veya yöntemin adını döndürecek bir Ekleme Yöntemi istiyorum (VB.Net'in Alt ve İşlevleri) Bu özellik / yöntem, çağrıldığı yerden aynı olabilir veya olamaz. - Nikhil Agrawal
Bu çok kullanışlı! Teşekkürler! - Ben Pretorius


Bu görünüşe göre boks / kutulama ile ilgili. Boks gerektiren değer türlerini döndüren Lambda ifadeleri, UnaryExpressions olarak temsil edilirken, referans türlerini döndürenler, MemberExpressions olarak temsil edilir.


5
2017-11-28 07:58



Bu, en yüksek puanlı cevap üzerinde durur ve sadece cevaptan memnun olmayanlar için daha fazla fikir verir. - gregsonian


Bu soruyu sorduktan sonra (evet ben OP'im) Jon

ve ben bununla geldim

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;
}
}

4
2017-09-14 11:05