第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

通過(guò) ILGenerator 調(diào)用帶有謂詞表達(dá)式的 LINQ

通過(guò) ILGenerator 調(diào)用帶有謂詞表達(dá)式的 LINQ

C#
吃雞游戲 2022-07-23 17:17:54
我正在嘗試通過(guò)在運(yùn)行時(shí)發(fā)出 IL 來(lái)編譯 DynamicMethod。我希望它執(zhí)行以下操作:array.OrderByDesc( /* Select Field/Property Expression*/ ).ToArray();編譯 DynamicMethod 的方法有一個(gè)FieldInfo變量,我想將它用于OrderByDesc需要的表達(dá)式。這是我到目前為止所擁有的:public static FilterDelegate<T> CreateDelegate<T>( Expression<Func<T, double>> expression ){  var field = expression.GetFieldInfo();// Extension, gets FieldInfo from expression  ...  il.Emit( OpCodes.Ldloc_1 ); // Loads an array (T[])  il.Emit( OpCodes.Call, typeof( Enumerable ).GetMethod( nameof( Enumerable.OrderByDescending ), new Type[0]).MakeGenericMethod( typeof( T ) ) );  il.Emit( OpCodes.Call, typeof( Enumerable ).GetMethod( nameof( Enumerable.ToArray ) ).MakeGenericMethod( typeof( T ) ) );  il.Emit( OpCodes.Stloc_1 ); // Stores the sorted array}需要注意的幾點(diǎn):提供的表達(dá)式是一個(gè)選擇器,它指定在整個(gè)編譯方法中使用哪個(gè)字段(或?qū)傩灾С种担_@個(gè)方法不僅僅是調(diào)用OrderByDescending(),還包含很多低級(jí)優(yōu)化。排除排序,預(yù)計(jì)在大多數(shù)情況下運(yùn)行時(shí)間低于 40ns。如何將表達(dá)式傳遞給編譯方法或FieldInfo正確調(diào)用OrderByDescending()?
查看完整描述

1 回答

?
隔江千里

TA貢獻(xiàn)1906條經(jīng)驗(yàn) 獲得超10個(gè)贊

我不完全理解你想通過(guò)直接 IL 生成來(lái)實(shí)現(xiàn)什么;OrderByDescending接受一個(gè)Func<TSource, TKey>名為“keySelector”的參數(shù)。因此,您在仍然使用此方法時(shí)唯一可以生成的 IL 只是一個(gè)常規(guī)方法調(diào)用,它將“keySelector”參數(shù)傳遞給該方法,除非您打算在 ILOrderByDescending中重新實(shí)現(xiàn)。OrderByDescending


你有什么理由需要一直下到 IL 嗎?


如果這是用于用戶級(jí)代碼,您可以“編譯”expression將傳遞給此方法并OrderByDescending()正常調(diào)用的代碼,例如


var expression = /* Select Field/Property Expression*/;

array.OrderByDescending(expression.Compile()).ToArray();

如果這是框架/實(shí)用程序級(jí)別的代碼,您可能會(huì)使用“表達(dá)式樹(shù)”而無(wú)需一直使用手動(dòng) IL。例如


public static FilterDelegate<T> CreateDelegate<T>(Expression<Func<T, double>> expression)

{

    var parameter = Expression.Parameter(typeof(IEnumerable<T>), "source");


    // Your `GetMethod` for OrderByDescending did not work for me,

    // so I'll just hand wave about this.

    var orderByDescMethod = typeof(Enumerable)

        .GetMethods()

        .Single(m => m.Name == nameof(Enumerable.OrderByDescending) &&

                     m.GetParameters().Length == 2)

        .MakeGenericMethod(typeof(T), typeof(double));


    var toArrayMethod = typeof(Enumerable)

        .GetMethod(nameof(Enumerable.ToArray))

        .MakeGenericMethod(typeof(T));


    var orderByExpression = Expression.Call(orderByDescMethod, parameter, expression);

    var lambdaBody = Expression.Call(toArrayMethod, orderByExpression);

    var lambdaExpression = Expression.Lambda<FilterDelegate<T>>(lambdaBody, parameter);


    return lambdaExpression.Compile();

}

但是,如果由于某種原因您仍然需要直接通過(guò) IL 發(fā)出它,那么類(lèi)似下面的東西可以工作。


public static FilterDelegate<T> CreateDelegate<T>(Expression<Func<T, double>> expression)

{

    // Your `GetMethod` for OrderByDescending did not work for me,

    // so I'll just hand wave about this.

    var orderByDescMethod = typeof(Enumerable)

                            .GetMethods()

                            .Single(m => m.Name == nameof(Enumerable.OrderByDescending) &&

                                         m.GetParameters().Length == 2)

                            .MakeGenericMethod(typeof(T), typeof(double));


    var toArrayMethod = typeof(Enumerable)

                        .GetMethod(nameof(Enumerable.ToArray))

                        .MakeGenericMethod(typeof(T));


    // TODO: if you don't already have one of these

    //       you'll probably want to pull this out and re-use it

    //       rather than making a new one for every delegate

    // TODO: if you do share a module builder I don't think it's thread-safe

    //       so this method will need sufficient locking/synchronization

    var dynamicAssemblyName = new AssemblyName { Name = $"{Guid.NewGuid()}" };

    var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);

    var module = asm.DefineDynamicModule(dynamicAssemblyName.Name);


    // Create a class with a static field to hold our compiled expression

    var typeBuilder = module.DefineType(

        $"{Guid.NewGuid()}",

        TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Serializable);


    var compiledExpressionField = typeBuilder.DefineField(

        "CompiledExpression",

        typeof(Func<T, double>),

        FieldAttributes.Static | FieldAttributes.Private);


    var holderType = typeBuilder.CreateType();


    var compiledExpression = expression.Compile();


    // Get the actual field after we've compiled the type

    var compiledExpressionFieldInfo = holderType.GetField(

        compiledExpressionField.Name,

        BindingFlags.Static | BindingFlags.NonPublic);


    // Store the compiled expression in the static field

    compiledExpressionFieldInfo.SetValue(null, compiledExpression);


    var newDelegate = new DynamicMethod($"{Guid.NewGuid()}",

        typeof(IOrderedEnumerable<T>),

        new[] { typeof(IEnumerable<T>) },

        typeof(ILGen), true);


    var il = newDelegate.GetILGenerator();


    // Load the array passed into the Delegate (T[])

    il.Emit(OpCodes.Ldarg_0);

    // Load the compiled expression from a static field

    il.Emit(OpCodes.Ldsfld, compiledExpressionFieldInfo);

    // Call .OrderByDescending()

    il.Emit(OpCodes.Call, orderByDescMethod);

    // Call .ToArray()

    il.Emit(OpCodes.Call, toArrayMethod);

    il.Emit(OpCodes.Ret); // Stores the sorted array


    return (FilterDelegate<T>)newDelegate.CreateDelegate(typeof(FilterDelegate<T>));

}



查看完整回答
反對(duì) 回復(fù) 2022-07-23
  • 1 回答
  • 0 關(guān)注
  • 129 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)