Question

Je voudrais créer un délégué et une méthode qui peut être utilisé pour appeler un certain nombre de services Web que mon application nécessite:

Exemple:

public DateCheckResponseGetDate(DateCheckRequest requestParameters)
{
    delegate object WebMethodToCall(object methodObject);

    WebMethodToCall getTheDate = new WebMethodToCall(WebServices.GetTheDate);

    return (DateCheckResponse)CallWebMethod(getTheDate , requestParameters);
}

public TimeCheckResponse GetTime(TimeCheckRequest requestParameters)
{
    delegate object WebMethodToCall(object methodObject);

    WebMethodToCall getTheTime = new WebMethodToCall(WebServices.GetTheTime);

    return (TimeCheckResponse)CallWebMethod(getTheTime, requestParameters);
}

private object CallWebMethod(WebMethodToCall method, object methodObject)
{
    return method(methodObject);
}

Mais, malheureusement, quand je tente de compiler, je reçois ces erreurs:

  

Pas de surcharge pour les délégués des matchs « GetTheDate » « WebMethodToCall »   Aucune surcharge pour 'GetTheTime' apparie délégué 'WebMethodToCall'

Il semble que le délégué devrait fonctionner.

WebServices.GetTheDate et WebServices.GetTheTime deux prennent un seul paramètre (DateCheckRequest et TimeCheckRequest, respectivement) et à la fois renvoyer une valeur.

ne pas le délégué correspond à la signature des deux méthodes Web? (À la fois accepter et renvoyer les types dérivés de l'objet).

Est-il possible d'utiliser le type d'objet pour faire un délégué très réutilisable dans .NET 2.0?

Était-ce utile?

La solution

Je vous suggère d'utiliser un délégué générique tel que Func<T, TResult>:

public DateCheckResponseGetDate(DateCheckRequest requestParameters)
{
    // Split declaration/assignment just to avoid wrapping
    Func<DateCheckRequest, DateCheckResponse> method;
    method = WebServices.GetTheDate;
    return CallWebMethod(method, requestParameters);
}

Vous auriez alors faites CallWebMethod générique aussi:

public TResponse CallWebMethod<TRequest, TResponse>
    (Func<TRequest, TResponse> method, TRequest request)
{
    // Whatever you do in here.
}

Autres conseils

Je vous suggère de changer votre code à quelque chose comme:


public DateCheckResponseGetDate(DateCheckRequest requestParameters)
{
    Func<DateCheckRequest, DateCheckResponse> getTheDate = new Func<DateCheckRequest, DateCheckResponse>(WebServices.GetTheDate);

    return CallWebMethod(getTheDate , requestParameters);
}

//DEFINE CallWebMethod ADEQUATELY!
public T CallWebMethod<T,U> (Func<T,U> webMethod, U arg)
{
    return webMethod(arg);
}

De cette façon, vous pouvez éviter tous les downcasting laid:)

Je l'ai travaillé à grâce aux commentaires ici.

private delegate object WebMethodToCall<T>(T methodObject);

public DateCheckResponseGetDate(DateCheckRequest requestParameters)
{
    WebMethodToCall<DateCheckRequest> getTheDate = new WebMethodToCall<DateCheckRequest>(WebServices.GetTheDate);

    return CallWebMethod<DateCheckResponse, DateCheckRequest>(getTheDate, requestParameters);
}

public TimeCheckResponse GetTime(TimeCheckRequest requestParameters)
{
    WebMethodToCall<TimeCheckRequest> getTheTime = new WebMethodToCall<TimeCheckRequest>(WebServices.GetTheTime);

    return CallWebMethod<TimeCheckResponse, TimeCheckRequest>(getTheTime, requestParameters);
}

private T CallWebMethod<T, U>(WebMethodToCall<U> method, U methodObject)
{
    return (T)method(methodObject);
}

Oui, mais il faudrait réécrire WebServices.GetTheData et GetTheTime de prendre des objets, ou de fournir des objets qui prennent les surcharges.

Ceci est parce que vous ne pouvez pas upcast objets dans .NET implicitement. En d'autres termes, vous pouvez faire ceci:

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

mais vous ne pouvez pas faire ceci:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

Vous pouvez définir Func comme:

public delegate TResult Func<T, TResult>(T arg);

Cette définition exige que rien n'est pas disponible dans .NET 2.0 et ajouté au Snipped que j'ai posté ci-dessus votre problème résout:)

Mise à jour: ne peut plus être valide? J'sais, je l'ai fait en C # 2.0

Pour développer la réponse de Will, alors que .NET ne le fera pas pour vous, vous pouvez implicitement forcer en ajoutant un opérateur implicite à votre classe TimeCheckRequest:

public class TimeCheckRequest
{
    ...

    public static implicit operator TimeCheckRequest(object request)
    {
        return (TimeCheckRequest) request;
    }
}

Je voudrais pas recommander cela, cependant, puisque vous pouvez utiliser un délégué générique au lieu sans le coût de la performance de tout le casting.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top