2013-10-15 5 views
1

фона:Делегат возвращения данных зависит от вызывающего абонента

  • У меня есть 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; 
} 

Раздел 3 и раздел 1 объявлены в том же классе, используя примеры SDK.

Я искал решение за последние 5 часов, но я не могу обернуть голову делегатами. Некоторая предыдущая публикация в SO предложила использовать делегат.Caller, но я не понимаю, как она используется, и я даже не уверен, что она применима в этом случае?

Любое предложение, как с этим бороться?

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

Если вам нужен экземпляр X в getRows, вы могли бы сделать что-то вроде:

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

Поскольку блоки itertator (aka 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); 
    } 
} 
+0

Это, по-видимому, действительный подход. Однако мне нужно немного больше рекомендаций. Визуальная студия жалуется на отчет о доходности. «Оператор yield не может использоваться внутри выражения лямбда:« Я чувствую себя настолько глупо сейчас – Anders

+0

@ Anders Ah, да, 'yield' не будет работать в анонимной функции. Я буду обновлять свой ответ, если вам действительно нужно «урожай» работать. – sloth

+0

@Anders обновил мой ответ – sloth

0

Если у вас есть контроль над классом, отображающим делегат, просто измените делегат, чтобы принять аргумент для вызывающего. В противном случае вам не повезло.

Независимо от того, эта архитектура в лучшем случае сомнительна.

+0

Я могу продлить его.Возможно ли перегрузить подпись делегата так же, как и любой другой метод: 'public delegate IEnumerable GetRowsHandler (список данных);'? Визуальная студия, похоже, удовлетворена по крайней мере. Однако я не уверен, как передать аргумент делегату при использовании этого метода. – Anders

Смежные вопросы