Pregunta

Me gustaría crear un delegado y un método que puede ser usado para llamar a cualquier número de servicios Web que mi aplicación requiere:

Ejemplo:

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

Pero, por desgracia, cuando intento compilar, obtengo estos errores:

  

No hay sobrecarga de partidos 'GetTheDate' delegado 'WebMethodToCall'   No hay sobrecarga de partidos 'GetTheTime' delegado 'WebMethodToCall'

Parece que el delegado debe trabajar.

WebServices.GetTheDate y WebServices.GetTheTime ambos toman un único parámetro (DateCheckRequest y TimeCheckRequest, respectivamente) y ambos devolver un valor.

Así que no el delegado coincide con la firma de los dos métodos web? (Tanto aceptar y tipos derivados de objeto de retorno).

¿Es posible utilizar el tipo de objeto para hacer un delegado muy reutilizable en .NET 2.0?

¿Fue útil?

Solución

Le sugiero que use un delegado genérico como 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);
}

Se podría entonces hacer CallWebMethod genérica también:

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

Otros consejos

Te sugiero que cambie su código a algo como:


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 esta manera se puede evitar toda la downcasting fea:)

He trabajado a cabo gracias a los comentarios aquí.

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í, pero habría que reescribir WebServices.GetTheData y GetTheTime tomar objetos, o proporcionar sobrecargas que toman los objetos.

Esto es porque no se puede upcast objetos en .NET de forma implícita. En otras palabras, se puede hacer esto:

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

pero no se puede hacer esto:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

Es posible definir Func como:

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

Esta definición no requiere nada que no está disponible en .NET 2.0 y se añade a la corté He publicado mencionadas resuelve su problema:)

ACTUALIZACIÓN: puede que ya no sea válida? No sé, yo he hecho esto en C # 2.0

Para ampliar la respuesta de Will, mientras .NET no va a hacer esto para usted implícitamente puede forzar mediante la adición de un operador implícito a su clase TimeCheckRequest:

public class TimeCheckRequest
{
    ...

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

Me no recomendar este, sin embargo, ya que se puede utilizar un delegado genérico lugar sin el costo de adquirir todo el casting.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top