2016-12-01 2 views
0

Dies ist mein Code, der Eigenschaft T Objekt von property Zeichenfolge generiert.Linq: OrderBy dynamische geschachtelte Eigenschaft, die null sein kann

// returning property as lambda from string 
public static Func<T, object> GetPropertyFunc<T>(string property) 
{ 
    try 
    { 
     var parameter = Expression.Parameter(typeof(T), "obj"); 

     Expression body = parameter; 
     foreach (var member in property.Split('.')) 
     { 
      body = Expression.PropertyOrField(body, member); 
     }    

     // conversion from Toutput to object 
     Expression converted = Expression.Convert(body, typeof(object)); 

     return Expression.Lambda<Func<T, object>>(converted, parameter).Compile(); 

     //return (Func<T, object>)Expression.Lambda(body, parameter).Compile(); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
} 

Als nächstes, ich benutze es hier:

var orderParamFunc = PagedListHelper.GetPropertyFunc<T>(pagedListModel.OrderParameter.ParameterName); 

IOrderedEnumerable<T> finalQuery = pagedListModel.OrderParameter.OrderAscending ? whereQuery.OrderBy(orderParamFunc) : whereQuery.OrderByDescending(orderParamFunc); 

Es ist gut funktioniert, wenn Eigenschaft nicht null ist. Ich habe Problem mit Beispiel:

property = "Customers.Dicts.DictValue"

in T Objekt Customers Eigenschaft null sein kann entweder Customers.Dicts Eigenschaft sein kann.

Was soll ich zu GetPropertyFunc Methode hinzufügen, um Prüfungen von Null zu machen? Ich weiß nicht, wo und wie man die Bedingung != null oder .HasValue setzen kann.

Antwort

1

Wie in diesem Beitrag vorgestellt:

How to detect IsNull/NotNull when building dynamic LINQ expressions?

Ich würde vorschlagen, die foreach-Schleife zu ändern für die Standardwerte (null) zu als Ausdruck in Bezug auf Werttypen konstruiert zu überprüfen. Hier

ist eine kleine Hilfe für den Bau von Standard-Werttyp:

Programmatic equivalent of default(Type)

Hier ist der Unit-Test:

using System; 
using System.Text; 
using System.Collections.Generic; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Linq.Expressions; 

namespace TestProject1 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     class TestRefType2 
     { 
      public TestRefType2() 
      { 

      } 
     } 

     class TestRefType1 
     { 
      public TestRefType1() 
      { 

      } 

      public Guid VALUETYPE { get; set; } 
      public TestRefType2 REFTYPE { get; set; } 
     } 

     class MainType 
     { 
      public MainType() 
      { 

      } 

      public TestRefType1 REFTYPE { get; set; } 
     } 

     public static object GetDefault(Type type) 
     { 
      if (type.IsValueType) 
      { 
       return Activator.CreateInstance(type); 
      } 
      return null; 
     } 

     // returning property as lambda from string 
     public static Func<T, object> GetPropertyFunc<T>(string property) 
     { 
      try 
      { 
       var parameter = Expression.Parameter(typeof(T), "obj"); 

       Expression body = parameter; 
       foreach (var member in property.Split('.')) 
       { 
        var prop = Expression.PropertyOrField(body, member); 
        body = Expression.Condition(Expression.Equal(body, Expression.Default(body.Type)), Expression.Default(prop.Type), prop); 
       } 

       // conversion from Toutput to object 
       Expression converted = Expression.Convert(body, typeof(object)); 

       return Expression.Lambda<Func<T, object>>(converted, parameter).Compile(); 

       //return (Func<T, object>)Expression.Lambda(body, parameter).Compile(); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     [TestMethod] 
     public void TestMethod1() 
     { 
      MainType t = new MainType(); 
      t.REFTYPE = new TestRefType1(); 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE"); 
      object val = ex(t); 

      Assert.AreEqual(default(Guid), val); 
     } 

     [TestMethod] 
     public void TestMethod2() 
     { 
      MainType t = new MainType(); 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE"); 
      object val = ex(t); 

      Assert.AreEqual(default(Guid), val); 
     } 

     [TestMethod] 
     public void TestMethod3() 
     { 
      MainType t = new MainType(); 
      t.REFTYPE = new TestRefType1(); 
      var guid = Guid.NewGuid(); 
      t.REFTYPE.VALUETYPE = guid; 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE"); 
      object val = ex(t); 

      Assert.AreEqual(guid, val); 
     } 

     [TestMethod] 
     public void TestMethod4() 
     { 
      MainType t = new MainType(); 
      t.REFTYPE = new TestRefType1(); 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE"); 
      object val = ex(t); 

      Assert.AreNotEqual(default(TestRefType1), val); 
     } 

     [TestMethod] 
     public void TestMethod5() 
     { 
      MainType t = new MainType(); 
      t.REFTYPE = new TestRefType1(); 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE"); 
      object val = ex(t); 

      Assert.AreEqual(default(TestRefType2), val); 
     } 

     [TestMethod] 
     public void TestMethod6() 
     { 
      MainType t = new MainType(); 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE"); 
      object val = ex(t); 

      Assert.AreEqual(default(TestRefType2), val); 
     } 

     [TestMethod] 
     public void TestMethod7() 
     { 
      MainType t = new MainType(); 
      t.REFTYPE = new TestRefType1(); 
      var reftype2 = new TestRefType2(); 
      t.REFTYPE.REFTYPE = reftype2; 

      Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE"); 
      object val = ex(t); 

      Assert.AreEqual(reftype2, val); 
     } 

    } 
} 
+0

Ausnahme: "Falsche Argumenttypen". – Staly

+0

yep ich das korrigiert und fügte einen vollständigen Test –

+0

Kann nicht sehen, dass Sie diese Zeilen behoben, immer noch ein Fehler. – Staly

0

Sie müssen vor dem Aufruf der Methode GetPropertyFunc nach Nullwerten für diese Eigenschaften suchen. Auf diese Weise gibt die Methode GetPropertyFunc ein Lambda zurück, das diese Eigenschaften nicht enthält.

Ehrlich gesagt bin ich nicht sicher, was Sie versuchen, außer dass Sie versuchen, eine Abfrage zu erstellen, die Sie schließlich irgendwo verwenden werden. Vielleicht gibt es einen besseren Weg, um das zu erreichen, was Sie wollen, wenn wir Ihr Ziel und Ihre Absicht kennen.

+0

Ich weiß nicht, über nulls vor diesem Verfahren, weil ich Zeichenfolge, die in Eigenschaft konvertiert werden muss. – Staly

+0

Sie müssen die Zeichenfolge analysieren und herausfinden, ob Ihr Zielobjekt über diese Eigenschaften verfügt, und sicherstellen, dass diese Eigenschaften nicht null sind. Dann erstelle das Lambda. Wenn Sie das Lambda haben, bevor Sie nach Nullen suchen, dann müssen Sie es, sobald Sie herausfinden, dass eine Eigenschaft null ist, irgendwie aus Ihrem Lambda entfernen; Deshalb sollten Sie zuerst nach Nullen suchen. Es gibt keinen anderen Weg. – CodingYoshi

Verwandte Themen