23

我有一个Thing可以从string. 当我直接调用带有Thing参数的方法时,从stringto的转换Thing是正确的。

但是,如果我使用反射来调用相同的方法,则会引发异常

System.ArgumentException : Object of type 'System.String' cannot be 
converted to type 'Things.Program+Thing'.

也许有一个很好的理由,但我无法弄清楚。有人知道如何使用反射来完成这项工作吗?

namespace Things
{
    class Program
    {
        public class Thing
        {
            public string Some;

            public static implicit operator Thing(string s)
            {
                return new Thing {Some = s};
            }
        }

        public void showThing(Thing t)
        {
            Console.WriteLine("Some = " + t.Some);
        }

        public void Main()
        {
            showThing("foo");
            MethodInfo showThingReflected = GetType().GetMethod("showThing");
            showThingReflected.Invoke(this, new dynamic[] {"foo"});
        }
    }
}

Meta:请不要讨论为什么隐式转换或反射是不好的。

4

3 回答 3

17

诀窍是要意识到编译器会op_Implicit为您的隐式转换运算符创建一个特殊的静态方法。

object arg = "foo";

// Program.showThing(Thing t)
var showThingReflected = GetType().GetMethod("showThing");

// typeof(Thing)
var paramType = showThingReflected.GetParameters()
                                  .Single()
                                  .ParameterType; 

// Thing.implicit operator Thing(string s)
var converter = paramType.GetMethod("op_Implicit", new[] { arg.GetType() });

if (converter != null)
    arg = converter.Invoke(null, new[] { arg }); // Converter exists: arg = (Thing)"foo";

// showThing(arg)
showThingReflected.Invoke(this, new[] { arg });
于 2012-07-19T15:15:09.213 回答
5

找到了一个使用 TypeConverter 的答案(正如 Saeed 提到的)
似乎可以完成这项工作。

使用反射时进行隐式转换的 TypeConverter

于 2012-07-18T15:33:55.340 回答
1

在这种特定情况下,您可以通过数组类型进行转换,即

showThingReflected.Invoke(this, new Thing[] {"foo"});

但这是一种“作弊”。通常,您不能期望Invoke考虑您的 user-defined implicit operator。这种转换必须在编译时推断。

于 2012-07-18T15:30:00.633 回答