Как использовать отражение, чтобы вызвать метод и передать параметры, типы которых неизвестны во время компиляции? - PullRequest
3 голосов
/ 14 мая 2010

Я бы хотел динамически вызывать методы класса со значениями параметров, которые "анализируются" из строкового ввода.

Например: Я хотел бы вызвать следующую программу с этими командами:

c:> myprog.exe Метод A System.Int32 777
c:> myprog.exe Метод A System.float 23.17
c:> myprog.exe MethodB System.Int32 & 777
c:> myprog.exe MethodC System.Int32 777 System.String ThisCanBeDone

static void Main(string[] args)
{
     ClassA aa = new ClassA();
     System.Type[] types = new Type[args.Length / 2];
     object[] ParamArray = new object[types.Length];

     for (int i=0; i < types.Length; i++)
       {
          types[i] = System.Type.GetType(args[i*2 + 1]);
      // LINE_X: this will obviously  cause runtime error invalid type/casting
          ParamArray[i] = args[i*2 + 2];  

     MethodInfo callInfo = aa.GetType().GetMethod(args[0],types);
     callInfo.Invoke(aa, ParamArray);
}

// В неизменяемой библиотеке классов:

публичный класс ClassA { public void MethodA (int i) {Console.Write (i.ToString ()); }

    public void MethodA(float f) { Console.Write(f.ToString()); }

    public void MethodB(ref int i) { Console.Write(i.ToString()); i++; }

    public void MethodC(int i, string s) { Console.Write(s + i.ToString()); }

    public void MethodA(object o) { Console.Write("Argg! Type Trapped!"); }
}

«LINE_X» в вышеприведенном коде - липкая часть. Во-первых, я не знаю, как присвоить значение для параметра int или ref int даже после того, как я его создаю с помощью Activator.CreatInstance или чего-то еще. На ум приходит typeConverter, но для этого также требуется явное приведение типов к компиляции.

Я смотрю на CLR с очками JavaScript или есть способ сделать это?

Ответы [ 2 ]

3 голосов
/ 14 мая 2010

Попробуйте это:

void Main(string[] args)
{
 ClassA a = new ClassA();
 System.Type[] types = new Type[(args.Length -1) / 2];
 object[] ParamArray = new object[types.Length];

 for (int i=0; i < types.Length; i++)
 {
      if(args[i*2 + 1].EndsWith("&"))
    {
        var type = System.Type.GetType(args[i*2 + 1].Substring(0,args[i*2 +1].Length - 1)); 
        ParamArray[i] = Convert.ChangeType(args[i*2 + 2],type);
        types[i] = System.Type.GetType(args[i*2 + 1]);
    }
    else
    {
        types[i] = System.Type.GetType(args[i*2 + 1]);
        ParamArray[i] = Convert.ChangeType(args[i*2 + 2],types[i]);
    }      
 }

 MethodInfo callInfo = typeof(ClassA).GetMethod(args[0],types);
 callInfo.Invoke(a, ParamArray);    

}

РЕДАКТИРОВАТЬ: Это должно заботиться о контрольных параметров

1 голос
/ 14 мая 2010

Вам нужно убрать &, чтобы конвертировать его, если вы хотите, чтобы ссылка работала:

  static void Main(string[] args)
  {
     ClassA a = new ClassA();
     int half_arg_length = args.Length / 2;
     System.Type[] param_types = new Type[half_arg_length];
     object[] param_values = new object[half_arg_length];

     for (int i = 0; i < half_arg_length; i++)
     {
        string string_type = args[i * 2 + 1];
        param_types[i] = System.Type.GetType(string_type);
        Type convert_type = System.Type.GetType(string_type.TrimEnd('&'));
        param_values[i] = Convert.ChangeType(args[i * 2 + 2], convert_type);
     }
     MethodInfo callInfo = typeof(ClassA).GetMethod(args[0], param_types);
     object res = callInfo.Invoke(a, param_values);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...