Domanda

Vorrei creare un delegato e un metodo che possa essere utilizzato per chiamare qualsiasi numero di servizi Web richiesti dalla mia applicazione:

Esempio:

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

Ma, sfortunatamente, quando provo a compilare, ottengo questi errori:

Nessun sovraccarico per "gettheDate" abbina delegate "webmethodtocall" Nessun sovraccarico per "getTheTime" abbina il delegato "WebMethodTocall"

Sembra che il delegato dovrebbe funzionare.

WebServices.GetTheDate e WebServices.GetTheTime accettano entrambi un singolo parametro (DateCheckRequest e TimeCheckRequest, rispettivamente) ed entrambi restituiscono un valore.

Quindi il delegato non corrisponde alla firma dei due metodi web?(entrambi accettano e restituiscono tipi derivati ​​dall'oggetto).

È possibile utilizzare il tipo di oggetto per creare un delegato molto riutilizzabile in .NET 2.0?

È stato utile?

Soluzione

Ti suggerisco di utilizzare un delegato generico come 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);
}

Allora faresti CallWebMethod anche generico:

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

Altri suggerimenti

Ti suggerirei di modificare il codice in qualcosa del tipo:


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

In questo modo puoi evitare tutti i brutti downcasting :)

L'ho risolto grazie ai commenti qui.

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

Sì, ma dovresti riscrivere WebServices.GetTheData e GetTheTime per accettare oggetti o fornire sovraccarichi che accettano oggetti.

Questo perché non puoi upcast oggetti in .NET in modo implicito.In altre parole, puoi fare questo:

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

ma non puoi farlo:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

Puoi definire Func come:

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

Questa definizione non richiede nulla che non sia disponibile in .NET 2.0 e aggiunta allo snipped che ho pubblicato sopra risolve il tuo problema :)

AGGIORNAMENTO: Potrebbe non essere più valido?Non lo so, l'ho fatto in C# 2.0

Per espandere la risposta di Will, mentre .NET non lo farà implicitamente per te, puoi forzarlo aggiungendo un operatore implicito alla tua classe TimeCheckRequest:

public class TimeCheckRequest
{
    ...

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

Vorrei non lo consiglio, tuttavia, poiché è possibile utilizzare a delegato generico invece senza il costo di esecuzione di tutto il casting.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top