2008-11-10 13 views
3

J'ai une classe qui stocke le nom d'une méthode WS à appeler et le type et la valeur du seul paramètre que le service reçoit (ce sera une collection de paramètres mais gardons-la simple pour l'exemple):appeler une méthode avec des paramètres obtenus à partir de la méthode générique

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); 
    } 
} 

J'ai une méthode qui prend le nom de la méthode et les paramètres et utilisant la réflexion appelle la méthode et renvoie le résultat. Que l'on fonctionne très bien quand je l'utilise comme ceci:

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

Mais mon type, décimal dans l'exemple, est donnée dans le cas de MethodCall. Donc, si j'ai ce code:

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

Option 1, ne compile pas:

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, ne compile pas ni:

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

Option 3, en utilisant la réflexion , compile mais ne fonctionne pas lorsque vous appelez le service:

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

callingclass.CallMethod(call.Method, Params); 

L'exception est la suivante: ConnectionLib.WsProxyParameterException: Les paramètres de la méthode 'TestService.Hello' dans l'URL 'http://localhost/MyTestingService/' sont incorrects.

Alors, quelqu'un peut-il me signaler la bonne façon de faire ce travail?

Merci

Répondre

2

Désolé, je aurais dû ajouter que si je fais ceci:

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

il fonctionne très bien, mais le point de l'ensemble de la méthode générique objet d'appel est d'éviter la coulée lorsque utilisé.

2

Vous ne pouvez pas simplement convertir une chaîne ("1") en nombre décimal, et même si vous pouviez douter que la version générique le sache ... elle essayerait de faire une distribution préservant la référence, où-comme vous auriez besoin d'une conversion d'opérateur (ils partagent la syntaxe en C#, mais sont très différents).

Donc, fondamentalement, je pense que Convert.ChangeType est votre seule option raisonnable ici.

J'ai effectivement some code qui vous permettra d'utiliser la conversion d'opérateur via des génériques, mais il n'y a pas de conversion d'opérateur entre la chaîne et la décimale, donc ça n'aiderait pas.

2

Si vous appelez la méthode avec réflexion, cela finira effectivement par être diffusé. Vous n'avez ici ni les avantages de la rapidité ni les avantages de la sécurité à la compilation des génériques - je ne pense pas que vous vous en serviez.

Generics sont utiles lorsque vous faites connaissez le type statiquement à la compilation, au moins quelque part. Le fait que vous ayez une propriété ParType va vraiment à l'encontre des génériques.