public static void EmitCast(this ILGenerator g, Type from, Type to) { if (from == to) { return; } if (to == typeof(object)) { g.EmitBox(from); } else if (from == typeof(object)) { g.EmitUnBoxAnyOrCastClass(to); } else { var method = MethodInfoEx.FindCastOperator(from, to); if (method != null) { g.EmitMethodCall(method); } else if (!to.IsAssignableFrom(from)) { g.Emit(OpCodes.Castclass, to); } } }
public void FindCastWorks() { var t1 = typeof(Cast1); var t2 = typeof(Cast2); Assert.Equal(typeof(int), MethodInfoEx.FindCastOperator(t1, typeof(int)).ReturnType); Assert.Equal(typeof(double), MethodInfoEx.FindCastOperator(t1, typeof(double)).ReturnType); Assert.Null(MethodInfoEx.FindCastToOperator(t1, typeof(string))); Assert.Null(MethodInfoEx.FindCastToOperator(t1, typeof(decimal))); Assert.Equal(typeof(int), MethodInfoEx.FindCastOperator(typeof(int), t2).GetParameterTypes()[0]); Assert.Equal(typeof(double), MethodInfoEx.FindCastOperator(typeof(double), t2).GetParameterTypes()[0]); Assert.Equal(t2, MethodInfoEx.FindCastOperator(t2, t1).GetParameterTypes()[0]); Assert.Null(MethodInfoEx.FindCastOperator(typeof(string), t2)); Assert.Null(MethodInfoEx.FindCastOperator(typeof(decimal), t2)); Assert.Throws <AmbiguousMatchException>(() => MethodInfoEx.FindCastOperator(t1, t2)); }