18

在某个类方法 A 中,我需要调用一个库方法 B,它以 anIProgress<Object>作为参数。

通常,我可能会IProgress<Object>作为 A 所在类的一部分实现,然后将“this”传递给方法 B。或者我可能会创建一个新类,其唯一目的是IProgress<Object>正确实现和处理它——那么在这种情况下,我d 创建该类的实例并将其传递给 B。

但我真正想要的是让我的实现IProgress<Object>出现在我调用 B 的方法中,这样调用代码和IProgress<Object>实现之间的视觉断开就会减少。(我认为我的 IProgress 实现是调用方法的一种私有的、非共享的细节,因此我不希望我的实现IProgress<Object>在一个完全独立的方法中,可能是另一个类)。

我一直在尝试做的是使用一个 lambda,我将在其中定义我的短进度处理,然后以某种方式将此 lambda 传递给 B,如下所示:

method in class A {
...
Action<Object> Report = (m) => { // do something useful with m };

B(Report)
}

method B(IProgress<Object> reporter) {
   reporter.Report(some object)
}

当然,我知道为什么这不能按原样工作 - B 想要一个实现的对象,IProgress<Object>而我将它交给一个 Action 对象。

有什么方法可以实现我想要实现的目标吗?IProgress<Object>(如果出现在方法 A 中,IE 有我的实现吗?

4

5 回答 5

16

代表不能(直接)实现接口。

想到两个不错的选择:

  1. 更改您要调用的方法的定义以采用委托类型而不是IProgress类型。(如果可能;这将是更可取的选择)

  2. 创建一个实现所需接口的新类型,并将委托作为参数来实现该功能。

#2 的示例虽然依赖于接口,但可能看起来像这样:

interface IProgress<T>
{
    void doStuff(T param);
}

class LambdaProgress<T> : IProgress<T>
{
    Action<T> action;
    public LambdaProgress(Action<T> action)
    {
        this.action = action;
    }

    public void doStuff(T param)
    {
        action(param);
    }
}

那么您就可以执行以下操作:

B(new LambdaProgress<Object>(obj => ...));
于 2012-09-17T16:01:42.313 回答
4

不,当需要接口时,您不能提供 lambda。但是您可以使用impromptu-interface
提供匿名对象。

此示例来自其项目页面:

//Anonymous Class
var anon = new
{
    Prop1 = "Test",
    Prop2 = 42L,
    Prop3 = Guid.NewGuid(),
    Meth1 = Return<bool>.Arguments<int>(it => it > 5)
}

var myInterface = anon.ActLike<IMyInterface>();

在您的示例中,这可以是:

A
{
    // Create an anonymous object.
    var anonymous = new
    {
        // Define a method that needs an "object" parameter and returns nothing.
        Report = Return.Arguments<object>(m =>
        {
            // Do whatever you want to do when Report is called.
        })
    }

    // Get your anonymous object as an IProgress<Object>.
    var obj = anonymous.ActLike<IProgress<Object>>

    // Call B.
    B(obj);
}
于 2012-09-17T16:27:58.043 回答
1

假设您的IProgress<object>接口只有一个void Report(object)方法,并且您控制 API,您可以简单地重新定义当前需要类型参数的方法,IProgress<object>而不是需要新的委托类型:

public delegate void ProgressReportDelegate(object someObject);

然后您的示例可以更改为:

method in class A {
...
Action<Object> Report = (m) => { // do something useful with m };

B(Report)
}

method B(ProgressReportDelegate reporter) {
   reporter(someObject);
}

对于更复杂的接口,或者您不控制 API(因此无法更改方法以获取委托而不是在实现该接口的对象上),这不是一个真正的选择,但它似乎可以工作在你的情况下。

于 2012-09-17T16:00:21.373 回答
-1

我相信何塞是这里唯一有效的答案,并帮助我解决了同样的问题。

从问题迈克尔想要调用方法“B”但使用 lambda 而不是实现 IProgress 接口:

method B(IProgress<Object> reporter) {
   reporter.Report(some object)
}

要在不创建需要实现 IProgress 接口的新类的情况下执行此操作,可以使用Progress类,因为它已经实现了 IProgress 接口。只需创建一个看起来像这样的 lambda 并将其传递到您的方法中:

var reporter = new Progress<int>((x) => 
{
   // call your own methods that use the reported value here
   MyProgressMethod.SetProgress(x);
});

现在您可以按照上面的问题在您的方法中使用它:

B(reporter);

或者,如果您想在一行中执行此操作:

B(new Progress<int>((x) => { progress.SetProgress(action, x); }));
于 2021-12-22T20:56:43.987 回答
-2

使用 .NET 4.5,您可以使用Progress

例子:

var reporter = new Progress<Object>((m) => {
  // do something useful with m
});

B(reporter);
于 2016-06-22T10:08:35.607 回答