C#委托可以使用对象类型更通用吗?

时间:2009-04-09 15:20:27

标签: c# functional-programming delegates type-conversion

我想创建一个委托和一个方法,可用于调用我的应用程序所需的任意数量的Web服务:

示例:

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)并且都返回一个值。

那么委托不匹配两个Web方法的签名吗? (接受和返回从对象派生的类型)。

是否可以使用对象类型在.NET 2.0中创建一个非常可重用的委托?

6 个答案:

答案 0 :(得分: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);
}

这样你可以避免所有丑陋的向下转换:)

答案 1 :(得分: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);
}

然后你也可以CallWebMethod通用:

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

答案 2 :(得分: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);
}

答案 3 :(得分:1)

是的,但你必须重写WebServices.GetTheData和GetTheTime来获取对象,或提供带对象的重载。

这是因为您无法隐式地在.NET中 upcast 对象。换句话说,你可以这样做:

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

但你不能这样做:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

答案 4 :(得分:0)

您可以将Func定义为:

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

此定义不需要.NET 2.0中没有的任何内容,并添加到我上面发布的剪辑中解决了您的问题:)

答案 5 :(得分:-1)

更新: 可能不再有效? Dunno,我在C#2.0

中完成了这个

要扩展Will的答案,而.NET不会隐式执行此操作,您可以通过向TimeCheckRequest类添加隐式运算符来强制执行此操作:

public class TimeCheckRequest
{
    ...

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

我会推荐这个,因为你可以使用generic delegate而不需要所有演员的演出费用。