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

时间:2021-02-21 22:05:34

I would like to create a delegate and a method that can be used to call any number of Web services that my application requires:

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

Example:

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

But, unfortunately, when I try to compile, I get these errors:

但是,不幸的是,当我尝试编译时,我收到了以下错误:

No overload for 'GetTheDate' matches delegate 'WebMethodToCall' No overload for 'GetTheTime' matches delegate 'WebMethodToCall'

“GetTheDate”没有重载匹配委托“WebMethodToCall”'GetTheTime'没有重载匹配委托'WebMethodToCall'

It seems like the delegate should work.

似乎代表应该工作。

WebServices.GetTheDate and WebServices.GetTheTime both take a single parameter (DateCheckRequest and TimeCheckRequest, respectively) and both return a value.

WebServices.GetTheDate和WebServices.GetTheTime都采用单个参数(分别为DateCheckRequest和TimeCheckRequest)并且都返回一个值。

So doesn't the delegate match the signature of the two web methods? (both accept and return types derived from object).

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

Is it possible to use the object type to make a very reusable delegate in .NET 2.0?

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

6 个解决方案

#1


I suggest you use a generic delegate such as Func<T, TResult>:

我建议你使用泛型委托,如Func : ,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 then make CallWebMethod generic too:

然后你也可以调用CallWebMethod:

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

#2


I'd suggest you change your code to something like:

我建议你将代码更改为:


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

This way you can avoid all of the ugly downcasting :)

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

#3


I worked it out thanks to the comments here.

由于这里的评论我把它解决了。

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

#4


Yes, but you'd have to rewrite WebServices.GetTheData and GetTheTime to take objects, or provide overloads that take objects.

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

This is because you can't upcast objects in .NET implicitly. In other words, you can do this:

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

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

but you can't do this:

但你不能这样做:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

#5


You may define Func as:

您可以将Func定义为:

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

This definition requires nothing that's not available in .NET 2.0 and added to the snipped I've posted above solves your problem :)

这个定义只需要在.NET 2.0中没有的东西,并添加到上面发布的剪辑中解决了你的问题:)

#6


UPDATE: May no longer be valid? Dunno, I've done this in C# 2.0

更新:可能不再有效? Dunno,我在C#2.0中完成了这个

To expand on Will's answer, while .NET will not do this for you implicitly you can force it by adding an implicit operator to your TimeCheckRequest class:

为了扩展Will的答案,虽然.NET不会隐式地为你做这个,你可以通过向TimeCheckRequest类添加一个隐式运算符来强制它:

public class TimeCheckRequest
{
    ...

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

I would not recommend this, however, since you can use a generic delegate instead without the performance cost of all the casting.

但是,我不建议这样做,因为您可以使用通用委托而不需要所有转换的性能成本。

#1


I suggest you use a generic delegate such as Func<T, TResult>:

我建议你使用泛型委托,如Func : ,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 then make CallWebMethod generic too:

然后你也可以调用CallWebMethod:

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

#2


I'd suggest you change your code to something like:

我建议你将代码更改为:


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

This way you can avoid all of the ugly downcasting :)

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

#3


I worked it out thanks to the comments here.

由于这里的评论我把它解决了。

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

#4


Yes, but you'd have to rewrite WebServices.GetTheData and GetTheTime to take objects, or provide overloads that take objects.

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

This is because you can't upcast objects in .NET implicitly. In other words, you can do this:

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

TimeCheckRequest myTimeCheckRequest;
object foo = myTimeCheckRequest;

but you can't do this:

但你不能这样做:

object myTimeCheckRequest;
TimeCheckRequest  foo = myTimeCheckRequest;

#5


You may define Func as:

您可以将Func定义为:

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

This definition requires nothing that's not available in .NET 2.0 and added to the snipped I've posted above solves your problem :)

这个定义只需要在.NET 2.0中没有的东西,并添加到上面发布的剪辑中解决了你的问题:)

#6


UPDATE: May no longer be valid? Dunno, I've done this in C# 2.0

更新:可能不再有效? Dunno,我在C#2.0中完成了这个

To expand on Will's answer, while .NET will not do this for you implicitly you can force it by adding an implicit operator to your TimeCheckRequest class:

为了扩展Will的答案,虽然.NET不会隐式地为你做这个,你可以通过向TimeCheckRequest类添加一个隐式运算符来强制它:

public class TimeCheckRequest
{
    ...

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

I would not recommend this, however, since you can use a generic delegate instead without the performance cost of all the casting.

但是,我不建议这样做,因为您可以使用通用委托而不需要所有转换的性能成本。