2009-04-09 2 views
2

Я хотел бы создать делегат и метод, который может быть использован для вызова любых веб-служб, что мое приложение требует:Может ли делегат C# использовать тип объекта более общим?

Пример:

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

Но, к сожалению, когда я пытаюсь скомпилировать , я получаю эти ошибки:

Нет перегрузки для 'GetTheDate' соответствует делегату 'WebMethodToCall' Нет перегрузки для 'GetTheTime' соответствует делегату 'WebMethodToCall'

Кажется, делегат должен работать.

WebServices.GetTheDate и WebServices.GetTheTime берут один параметр (DateCheckRequest и TimeCheckRequest соответственно) и оба возвращают значение.

Значит, делегат не соответствует подписи двух веб-методов? (как принимать, так и возвращать типы, полученные из объекта).

Возможно ли использовать тип объекта, чтобы сделать делегат с очень многократным повторением в .NET 2.0?

ответ

5

Я предлагаю вам использовать общий делегат, такие как 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); 
} 

You d затем сделать также CallWebMethod:

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

Я предлагаю вам изменить свой код, чтобы что-то вроде:


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

Таким образом, вы можете избежать все уродливого :)

понижающего приведения
+0

К сожалению, я придерживаюсь .NET 2.0, поэтому ваше решение не будет работать для меня. –

+0

.NET 2.0 поддерживает generics –

+0

Это правда, однако Func был добавлен с LINQ в .NET 3.5. – Andy

1

Да, но вам придется переписать WebServices. GetTheData и GetTheTime взять объекты или обеспечить перегрузки, которые берут объекты.

Это потому, что вы не можете upcast объектов в .NET неявно. Другими словами, вы можете сделать это:

TimeCheckRequest myTimeCheckRequest; 
object foo = myTimeCheckRequest; 

, но вы не можете сделать это:

object myTimeCheckRequest; 
TimeCheckRequest foo = myTimeCheckRequest; 
+0

Да, вы определенно правы в этом. Мой объект никогда не будет автоматически преобразован в TimeCheckRequest. Darn тип-безопасный язык. –

+0

Вы можете определить неявный оператор в классе TimeCheckRequest, чтобы сделать это без ручного нажатия на объект. –

+0

Создание неявного оператора для базового класса типа (esp. Для Object) не кажется лучшей идеей в мире ... Я не уверен, что есть какие-либо официальные заявления по этому вопросу, но у него есть запах об этом ... – Will

-1

ОБНОВЛЕНИЕ:Больше недействительны? Незнайка, я сделал это в C# 2.0

Чтобы расширить ответ Уилла, в то время как .NET не будет делать это для вас неявно вы можете заставить его путем добавления неявного оператора к классу TimeCheckRequest:

public class TimeCheckRequest 
{ 
    ... 

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

Я бы не рекомендую это, однако, вы можете использовать generic delegate вместо стоимости исполнения всего литья.

+0

Код не скомпилирован: ошибка CS0553: 'MyType.implicit operator MyType (object)': пользовательские преобразования в базовый класс или из него не допускаются –

+0

@WesleyWiser Я сделал это в C# 2.0, не знаю, работает ли он. –

0

Вы можете определить Func как:

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

Это определение не требует ничего, что не доступно в .NET 2.0 и добавил к отрезала я отправил выше решает вашу проблему :)

2

Я работал его благодаря комментариям здесь.

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); 
} 
Смежные вопросы