Подтвердить что ты не робот

Как неявно использовать вызов отраженного метода

У меня есть класс Thing, который неявно может быть спрятан от a string. Когда я вызываю метод с параметром Thing напрямую, выполняется отличное от string до 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"});
        }
    }
}

Мета: Пожалуйста, не обсуждайте, почему неявное литье или отражение плохо.

4b9b3361

Ответ 2

Трюк заключается в том, чтобы понять, что компилятор создает специальный статический метод под названием 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 });

Ответ 3

В этом конкретном случае вы можете выполнить преобразование через тип массива, то есть

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

но это своего рода "обман". В общем случае вы не можете ожидать, что Invoke рассмотрит ваш пользовательский implicit operator. Это преобразование должно быть выведенным временем компиляции.