вызвать метод с параметрами, полученными из универсального метода

У меня есть класс, хранящий имя вызываемого метода WS, а также тип и значение единственного параметра, который получает служба (это будет набор параметров, но для примера давайте упростим его):

public class MethodCall
{
  public string Method { get; set; }
  public Type ParType { get; set; }
  public string ParValue { get; set; }
  public T CastedValue<T>()
  {
    return (T)Convert.ChangeType(ParValue, ParType);
  }
}

У меня есть метод, который принимает имя метода и параметры и с помощью отражения вызывает метод и возвращает результат. Этот отлично работает, когда я использую его следующим образом:

callingclass.URL = url;
callingclass.Service = serviceName;
object[] Params = { (decimal)1 };
callingclass.CallMethod("Hello", Params);

Но мой тип, десятичный в примере, указан в экземпляре MethodCall. Итак, если у меня есть этот код:

MethodCall call = new MethodCall();
call.Method = "Hello";
call.ParType = typeof(decimal);
call.ParValue = "1";

Вариант 1, не компилируется:

object[] Params = { (call.ParType)call.ParValue }; //Compilation error: The type or namespace name 'call' could not be found (are you missing a using directive or an assembly reference?)

Вариант 2 тоже не компилируется:

object[] Params = { call.CastedValue<call.ParType>() }; //Compilation error: Cannot implicitly convert type 'call.ParType' to 'object'

Вариант 3, использующий отражение, компилируется, но не работает при вызове службы:

object[] Params = { typeof(MethodCall).GetMethod("CastedValue").MakeGenericMethod(call.ParType).Invoke(this, null) };

callingclass.CallMethod(call.Method, Params);

Исключение составляет: ConnectionLib.WsProxyParameterExeption: параметры для метода «TestService.Hello» в URL-адресе «http://localhost/MyTestingService/' неверны.

Так может ли кто-нибудь указать мне правильный способ сделать эту работу?

Спасибо


person Community    schedule 10.11.2008    source источник


Ответы (3)


Извините, я должен был добавить, что если я просто сделаю это:

object[] Params = { Convert.ChangeType(call.ParValue, call.ParType)};

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

person Community    schedule 10.11.2008

Вы не можете просто преобразовать строку ("1") в десятичное число, и даже если бы вы могли, я сомневаюсь, что универсальная версия узнает об этом... она попытается выполнить приведение с сохранением ссылок, где-как вы потребуется преобразование оператора (они имеют общий синтаксис C#, но очень разные).

В общем, я думаю, что Convert.ChangeType - ваш единственный разумный вариант.

У меня есть некоторый код, который позволит вам использовать преобразование оператора через дженерики, но нет преобразования оператора между строкой и десятичным числом, поэтому это не поможет.

person Marc Gravell    schedule 10.11.2008

Если вы вызываете метод с отражением, это все равно приведет к кастингу. У вас нет ни преимуществ скорости, ни преимуществ безопасности типа дженериков здесь - я действительно не думаю, что вы делаете себе какие-то одолжения, используя его.

Обобщения полезны, когда вы действительно знаете тип статически во время компиляции, по крайней мере, где-то. Тот факт, что у вас есть свойство ParType, действительно противоречит смыслу дженериков.

person Jon Skeet    schedule 10.11.2008