委托返回数据依赖于调用者

时间:2013-10-15 11:24:59

标签: c# delegates

背景

  • 我有1 ... *同一类(X)的对象。
  • 为对象提供一个委托,为其提取数据。
  • X类的所有对象都使用相同的委托。
  • X类的每个对象都需要一组不同的数据。
  • 我正在使用的SDK声明委托没有参数。

我不知何故需要检查调用委托的对象并根据该行为进行操作。

代码部分1:以下部分显示了创建类X对象的代码段。正如评论所述,getRows被定义为“回调”

public void getTables() {
    foreach(X currentTable in mapper.getTables()) {
        MTables.Add(new X {
            TableName = currentTable.getName(),
            GetRows = getRows,  //This is the delegate
            Fields = Fields.ToArray()
        });
    }
}

代码部分2:类X声明代理如下:

public X.GetRowsHandler GetRows { get; set; }
public delegate IEnumerable<QvxDataRow> GetRowsHandler();

代码第3部分:以下是函数“getRows”的伪代码

private IEnumerable<QvxDataRow> getRows() {         
    // foreach row belonging to calling instance of class X
        //yield return row;  
}

使用SDK示例在同一个类中声明了第3节和第1节。

我已经找了最近5个小时的解决方案,但我无法围绕代表们。以前关于SO的一些帖子表明可以使用delegare.Caller,但我不明白它是如何使用的,我甚至不确定它是否适用于这种情况?

有任何建议如何处理?

2 个答案:

答案 0 :(得分:1)

您可以使用闭包将getRows()中的代码包装到接受parameter的方法中:

public void getTables() {
    foreach(X currentTable in mapper.getTables()) {
        MTables.Add(new X {
            TableName = currentTable.getName(),
            GetRows = getRows(currentTable.getName()), 
            Fields = Fields.ToArray()
        });
    }
}

// this method now returns another method that matches GetRowsHandler 
private GetRowsHandler getRows(string tablename) {         
    // this lambda method uses the tablename parameter
    return () =>
    {
        // something with foreach row in table tablename
    };
}

如果您需要XgetRows的实例,则可以执行以下操作:

public void getTables() {
    foreach(X currentTable in mapper.getTables()) {
        var x = new X {
            TableName = currentTable.getName(),
            Fields = Fields.ToArray()
        });
        x.GetRows = getRows(x), 
        MTables.Add(x);
    }
}

private GetRowsHandler getRows(X instance) {         
    return () =>
    {
        // something with instance
    };
}

由于迭代器块(a.k.a。yield)在匿名函数内不起作用,您可以创建一个类来捕获参数而不是使用闭包:

class GetRowsWrapper
{
    X _instance;

    public Something(X instance)
    {
        _instance = instance;
    }

    public IEnumerable<QvxDataRow> getRows()
    {
        // do something with _instance
        yield return yourstuff;
    }
}

public void getTables() {
    foreach(X currentTable in mapper.getTables()) {
        var x = new X {
        TableName = currentTable.getName(),
        Fields = Fields.ToArray()
        });
        // lambda to wrap getRows into a GetRowsHandler
        x.GetRows = () => new GetRowsWrapper(x).getRows();
        MTables.Add(x);
    }
}

答案 1 :(得分:0)

如果您可以控制暴露委托的类,则只需更改委托以接受调用者的参数。否则你运气不好。

无论如何,这种架构充其量是值得怀疑的。