Reputation:
I have a class storing the name of a WS method to call and the type and value of the only parameter that service receives (it will be a collection of parameters but lets keep it simple for the example):
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);
}
}
I have a method that takes the method name and the parameters and using reflection calls the method and returns the result. That one works fine when i use it like this:
callingclass.URL = url;
callingclass.Service = serviceName;
object[] Params = { (decimal)1 };
callingclass.CallMethod("Hello", Params);
But my type, decimal in the example, is given in the instance of MethodCall. So if i have this code:
MethodCall call = new MethodCall();
call.Method = "Hello";
call.ParType = typeof(decimal);
call.ParValue = "1";
Option 1, doesn't compile:
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?)
Option 2, doesn't compile neither:
object[] Params = { call.CastedValue<call.ParType>() }; //Compilation error: Cannot implicitly convert type 'call.ParType' to 'object'
Option 3, using reflection, compiles but doesn't work when calling the service:
object[] Params = { typeof(MethodCall).GetMethod("CastedValue").MakeGenericMethod(call.ParType).Invoke(this, null) };
callingclass.CallMethod(call.Method, Params);
The exception is: ConnectionLib.WsProxyParameterExeption: The parameters for the method 'TestService.Hello' in URL 'http://localhost/MyTestingService/' are wrong.
So can someone point me the right way to make this work?
Thanks
Upvotes: 3
Views: 1208
Reputation: 1500515
If you're calling the method with reflection, that's going to effectively end up casting anyway. You don't have either the speed benefits or compile-time type safety benefits of generics here - I don't really think you're doing yourself any favours by using it.
Generics are useful when you do know the type statically at compile-time, at least somewhere. The fact that you've got a ParType
property really goes against the point of generics.
Upvotes: 2
Reputation: 1062780
You can't just cast a string ("1") to a decimal, and even if you could I doubt that the generic version would know about it... it would try to do a reference-preserving cast, where-as you'd need an operator conversion (they share syntax in C#, but are very different).
So basically, I think Convert.ChangeType is your only sensible option here.
I do have some code that will allow you to use operator conversion via generics, but there is no operator conversion between string and decimal, so it wouldn't help.
Upvotes: 2
Reputation:
Sorry, I should have added that if i just do this:
object[] Params = { Convert.ChangeType(call.ParValue, call.ParType)};
it works fine, but the whole point of the generic method in call object is to avoid the casting when being used.
Upvotes: 2