tarafından oluşturulan İfade Ağaçlarındaki parametrelerin açık bir şekilde dönüştürülmesi Aşağıda, (durağan olmayan) bir MethodInfo
'u derlediğim bir derlenmiş İfadeye (Func
) dönüştüren aşağıdaki yönteme sahibim.MethodInfo
Bu harika çalışır: Hem referans nesneleri hem de değer türlerini bekleyen bir yöntemle çağırabilirim.
AMA
Bendouble
bekliyor bir parametre olan bir yöntemini çağırın ve ona bir
int
o desteklemeyen bu derlenmiş ifadeyi geçmek ve bir
InvalidCastException
atar olabilir orijinal yöntemle aksine.
Normal yöntem çağrısı sırasında gerçekleşen aynı tür örtük yayınları desteklemek için bunu nasıl değiştirebilirim?
Bonus soru: instanceExp, DeclaringType
veya ReflectedType
'u MethodInfo
'dan mı kullanıyor?
public Func<object, object[], object> Create(MethodInfo methodInfo)
{
var methodParams = methodInfo.GetParameters();
var arrayParameter = Expression.Parameter(typeof(object[]), "array");
var arguments =
methodParams.Select((p, i) => Expression.Convert(
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)), p.ParameterType))
.Cast<Expression>()
.ToList();
var instanceParameter = Expression.Parameter(typeof(object), "controller");
var instanceExp = Expression.Convert(instanceParameter, methodInfo.DeclaringType);
var callExpression = Expression.Call(instanceExp, methodInfo, arguments);
var bodyExpression = Expression.Convert(callExpression, typeof(object));
return Expression.Lambda<Func<object, object[], object>>(
bodyExpression, instanceParameter, arrayParameter)
.Compile();
}
--- DÜZENLEME
çalışma çözümdür:
object a = 123;
double b = (double)a; // InvalidCastException
nedeni:
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var arguments =
methodParams.Select((p, i) =>
!typeof(IConvertible).IsAssignableFrom(p.ParameterType)
// If NOT IConvertible, don't try to convert it
? (Expression)Expression.Convert(
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)), p.ParameterType)
:
// Otherwise add an explicit conversion to the correct type to handle int <--> double etc.
(Expression)Expression.Convert(
Expression.Call(changeTypeMethod,
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)),
Expression.Constant(Type.GetTypeCode(p.ParameterType))),
p.ParameterType)
)
.ToList();
Tamam, ama bunu, 'Func' değerlendirilinceye kadar 'object' parametresinin içinde bir' int' kutulu olduğunu bilmediğimde bunu nasıl yaparım? Sihirli ifade nedir? Bu parametreyi, kendi türüne (nesneden) dönüştürmek için parametrenin etrafına sarmak ve sonra bunu arama için gerekli parametre türüne dönüştürmek zorunda mıyım? –
@IanMercer Bunu fark ettim, bu yüzden cevabımı geçmişte projelerimden birinde kullanmayı hatırladığım stratejiyle güncelledim. – dasblinkenlight
Gösterildiği gibi değiştirmeyi denedim ancak hala bir InvalidCastException alıyorum. Yazabileceğin bir kodun var mı? –