Я пытаюсь создать динамический Accessor Access. Хотите что-то, что по-настоящему быстро, как близко к названию на самом деле собственности. Не хочу идти по пути Отражения, так как он очень медленный. Поэтому я решил использовать DynamicAssembly и внедрить IL с помощью ILGenerator. Ниже приведен код, связанный с ILGenerator, который, кажется, работает
Label nulllabel = getIL.DefineLabel();
Label returnlabel = getIL.DefineLabel();
//_type = targetGetMethod.ReturnType;
if (methods.Count > 0)
{
getIL.DeclareLocal(typeof(object));
getIL.DeclareLocal(typeof(bool));
getIL.Emit(OpCodes.Ldarg_1); //Load the first argument
//(target object)
//Cast to the source type
getIL.Emit(OpCodes.Castclass, this.mTargetType);
//Get the property value
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Br_S,returnlabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Stloc_0);
getIL.MarkLabel(returnlabel);
getIL.Emit(OpCodes.Ldloc_0);
}
else
{
getIL.ThrowException(typeof(MissingMethodException));
}
getIL.Emit(OpCodes.Ret);
Итак, выше получите первый аргумент, который является объектом, который содержит свойство. коллекция методов содержит вложенное свойство, если оно есть. для каждого свойства я использую EmitCall, который помещает значение в стек, а затем я пытаюсь его упаковать. Это работает как шарм.
Единственная проблема в том, что если у вас есть свойство типа Order.Instrument.Symbol.Name и предполагается, что объект Instrument имеет значение null Затем код сгенерирует исключение нулевого объекта.
Так вот что я сделал, я ввел нулевую проверку
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
getIL.Emit(OpCodes.Stloc_0);
getIL.Emit(OpCodes.Ldloc_0);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Ceq);
getIL.Emit(OpCodes.Stloc_1);
getIL.Emit(OpCodes.Ldloc_1);
getIL.Emit(OpCodes.Brtrue_S, nulllabel);
getIL.Emit(OpCodes.Ldloc_0);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
Теперь этот код не работает, говоря, что объект / память повреждены и т. Д. Так что же не так с этим кодом. Я что-то здесь упускаю.
Заранее спасибо.