2013-09-24 33 views
0

如何產生這個拉姆達lambda來表達

() => SomeObj.SomeProp 

使用Expression.MakeMemberAccess,而這種方法。我知道如何生成SomeObj => SomeObj.SomeProp,但問題是()部分。這是以某種方式轉換爲DisplayClass。

謝謝。

這是調用UvediSortiranje方法的連接。如果我使用UvediSortiranje(「Naziv」)方法.OrderBy(()=> pfA.Naziv)一切都OK!

Firma fA = null; 
PrevodFirme pfA = null; 
Jezik jA = null; 

return this.Sesija.QueryOver<Firma>(() => fA) 
      .UvediSortiranje(sortirajPo, fA) //!!!! 
      .Left.JoinAlias(() => fA.Prevodi,() => pfA) 
      .UvediSortiranje(sortirajPo, pfA) //!!!! 
      .Left.JoinAlias(() => pfA.Jezik,() => jA) 
      .UvediSortiranje(sortirajPo, jA) //!!!! 
      .Where(Restrictions.Disjunction().Add(Restrictions.On(() => pfA.Id).IsIn(pfr)).Add(Restrictions.On(() => jA.Id).IsIn(jr))) 
      .Where(() => jA.Id == jezikId) 
      .Skip(odZapisa) 
      .Take(brojZapisa) 
      .List(); 

另一種方法是UvediSortiranje擴展方法:

public static class Ekst 
{ 
    public static IQueryOver<TRoot, TSubType> UvediSortiranje<TRoot, TSubType, T>(this IQueryOver<TRoot, TSubType> ovo, string sortirajPo, T klasa) where T : class 
    { 
     //provjeri da li sortiraj po zadovoljava konvenciju Objekat.Svojstvo i ako da, splituj ga na to 
     var niz = sortirajPo.Split('.'); 
     // provjeri da li postoje ova svojstva u ovom objektu i da li se poklapaju imena 

     if (niz.Length <= 0) return ovo; 

     if (/*typeof(TSubType).Name == niz[0]*/ typeof(T).Name == niz[0]) 
     { 
      //var arg = Expression.Constant(null, typeof(TSubType)); 
      //var body = Expression.Convert(Expression.PropertyOrField(arg, niz[1]), 
      // typeof(object)); 
      //var lambda = Expression.Lambda<Func<object>>(body); 


      var param = Expression.Constant(klasa, typeof(T)); 
      var key = typeof(T).GetMember(niz[1]).First(); 
      //var rhs = Expression.MakeMemberAccess(Expression.Constant(itemToCompare), key); 
      var lhs = Expression.MakeMemberAccess(param, key); 
      //var body = Expression.Equal(lhs, rhs); 

      var lambda = Expression.Lambda<Func<object>>(
      MemberExpression.MakeMemberAccess(param, key) 
     ); 

      //lambda = (() => Expression.PropertyOrField(arg, niz[1])); 

      return niz[2].ToLower() == "asc" ? ovo.OrderBy(lambda).Asc : ovo.OrderBy(lambda).Desc; 
     } 
     //u suprotnom vrcemo ovo bez ikakvog sortiranja 
     return ovo; 
    } 
} 
+0

似乎是一個非常明確的問題給我。 –

回答

0

我終於su cceeded。這是NHibernate解析obj1.propert1.propert2的問題,因爲localy範圍的lambda表達式。因此,我必須創建代碼以在運行時創建新類並將其傳遞給方法。

public static Type CreateMyNewType 
(string newTypeName, string propertyName, Type propertyType, Type baseClassType) 
    { 
     // create a dynamic assembly and module 
     AssemblyBuilder assemblyBldr = 
     Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("tmpAssembly"), 
     AssemblyBuilderAccess.Run); 
     ModuleBuilder moduleBldr = assemblyBldr.DefineDynamicModule("tmpModule"); 

     // create a new type builder 
     TypeBuilder typeBldr = moduleBldr.DefineType 
     (newTypeName, TypeAttributes.Public | TypeAttributes.Class, baseClassType); 

     // Generate a private field for the property 
     FieldBuilder fldBldr = typeBldr.DefineField 
     ("_" + propertyName, propertyType, FieldAttributes.Private); 
     // Generate a public property 
     PropertyBuilder prptyBldr = 
        typeBldr.DefineProperty(propertyName, 
      PropertyAttributes.None, propertyType, new Type[] { propertyType }); 
     // The property set and property get methods need the following attributes: 
     MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig; 
     // Define the "get" accessor method for newly created private field. 
     MethodBuilder currGetPropMthdBldr = 
        typeBldr.DefineMethod("get_value", GetSetAttr, propertyType, null); 

     // Intermediate Language stuff... as per Microsoft 
     ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator(); 
     currGetIL.Emit(OpCodes.Ldarg_0); 
     currGetIL.Emit(OpCodes.Ldfld, fldBldr); 
     currGetIL.Emit(OpCodes.Ret); 

     // Define the "set" accessor method for the newly created private field. 
     MethodBuilder currSetPropMthdBldr = typeBldr.DefineMethod 
     ("set_value", GetSetAttr, null, new Type[] { propertyType }); 

     // More Intermediate Language stuff... 
     ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator(); 
     currSetIL.Emit(OpCodes.Ldarg_0); 
     currSetIL.Emit(OpCodes.Ldarg_1); 
     currSetIL.Emit(OpCodes.Stfld, fldBldr); 
     currSetIL.Emit(OpCodes.Ret); 
     // Assign the two methods created above to the PropertyBuilder's Set and Get 
     prptyBldr.SetGetMethod(currGetPropMthdBldr); 
     prptyBldr.SetSetMethod(currSetPropMthdBldr); 
     // Generate (and deliver) my type 
     return typeBldr.CreateType(); 
    } 

    public static IQueryOver<TRoot, TSubType> UvediSortiranje<TRoot, TSubType, T>(this IQueryOver<TRoot, TSubType> ovo, string sortirajPo, T klasa, string naziv) 
    { 
     //provjeri da li sortiraj po zadovoljava konvenciju Objekat.Svojstvo i ako da, splituj ga na to 
     var niz = sortirajPo.Split('.'); 
     // provjeri da li postoje ova svojstva u ovom objektu i da li se poklapaju imena 

     if (niz.Length <= 0) return ovo; 

     if (/*typeof(TSubType).Name == niz[0]*/ typeof(T).Name == niz[0]) 
     { 
      //var arg = Expression.Constant(null, typeof(TSubType)); 
      //var body = Expression.Convert(Expression.PropertyOrField(arg, niz[1]), 
      // typeof(object)); 
      //var lambda = Expression.Lambda<Func<object>>(body); 


      var tip = CreateMyNewType("brza2", naziv, typeof(T), typeof(object)); 

      var newClassBase = Activator.CreateInstance(tip); 

      dynamic nesto = newClassBase; 

      var parameter = Expression.Parameter(nesto.GetType()); 
      var memberExpression = Expression.Property(parameter, naziv); 
      //var parameter2 = Expression.Parameter(typeof(T)); 
      var memberExpression2 = Expression.Property(memberExpression, niz[1]); 
      Expression conversion = Expression.Convert(memberExpression2, typeof(object)); 
      var lambda = Expression.Lambda<Func<object>>(conversion); 


      //lambda = (() => Expression.PropertyOrField(arg, niz[1])); 

      return niz[2].ToLower() == "asc" ? ovo.OrderBy(lambda).Asc : ovo.OrderBy(lambda).Desc; 
     } 
     //u suprotnom vrcemo ovo bez ikakvog sortiranja 
     return ovo; 
    } 
0

這是Expression.Lambda(body)

0

如果您知道如何生成SomeObj => SomeObj.SomeProp,那麼您應該可以通過調用Expression.Lambda來指定僅正文,從而生成不帶參數的lambda表達式。

所以有Foo => body你會做這樣的事情:

var lambdaExpression = Expression.Lambda(bodyExpression, Expression.Parameter(typeof(int), "Foo")); 

要有() => body你只是做:

var lambdaExpression = Expression.Lambda(bodyExpression); 

編輯:由於房地產在運行時提供的字符串(我猜這是屬性名稱):

LambdaExpression MakeLambda(Expression baseExpression, string fieldName) { 
    var member = typeof(Foo).GetMember(fieldName).First(); 
    var bodyExpression = Expression.MakeMemberAccess(baseExpression, member); 
    var lambdaExpression = Expression.Lambda(bodyExpression); 
} 
+0

對不起,只是對我的問題稍作修改。 SomeProp應該在運行時作爲字符串提供。所以應該引入一些變量x =「SomeProp」。我會嘗試你的建議,但我相信它會更復雜? – bojanv55

+0

@ user2779330它基本上是一樣的,真​​的。我在我的答案中添加了一個編輯,但代碼中幾乎沒有任何更改。還是你的意思是「運行時」,如「每次執行lambda時」而不是「何時構建lambda」? – luiscubal

+0

我希望這張圖片能幫上忙。 [IMG] http://i41.tinypic.com/ofrr5w.png [/ IMG] – bojanv55