0

如何生成这个 lambda

() => SomeObj.SomeProp

使用 Expression.MakeMemberAccess 和这种方法。我知道如何生成 SomeObj => SomeObj.SomeProp,但问题是 () 部分。这以某种方式翻译为 DisplayClass。

谢谢。

这是调用 UvediSortiranje 方法的连接。如果我使用 inestead UvediSortiranje("Naziv") 方法 .OrderBy(() => pfA.Naziv) 一切正常!

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

3 回答 3

0

那就是Expression.Lambda(body)

于 2013-09-24T21:18:41.560 回答
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);
}
于 2013-09-24T21:19:00.703 回答
0

我终于成功了。由于局部范围的 lambda 表达式,NHibernate 解析 obj1.propert1.propert2 是问题所在。因此,我必须创建代码以在运行时创建新类并将其传递给方法。

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;
    }
于 2013-09-26T22:06:50.063 回答