Как передать в метод в качестве параметра? - PullRequest
4 голосов
/ 10 декабря 2010

Я только что заметил, что я повторяю много кода C # в своем приложении ASP.NET, поэтому хочу создать универсальный метод. У меня есть ряд частных методов, таких как:

private void PopulateMyRepeatedControl()
{
    DBUtil DB = new DBUtil();
    DataTable symbols = GetSelectedSymbols();
    DataTable tradeGrades = GetSelectedTradeGrades();
    DataTable executionGrades = GetSelectedExecutionGrades();        

    chtMyRepeatedChart.DataSource = DB.MyRepeatedCall (
        int.Parse(txtStartBalance.Text),
        int.Parse(ddlTradeTypes.SelectedValue),
        ddlRepeatedTrades.SelectedValue,
        radSide.SelectedValue,
        ddlTradeSetups.SelectedValue,
        symbols,
        ddlChartTimeFrames.SelectedValue,
        int.Parse(ddlHours.SelectedValue),
        int.Parse(ddlYears.SelectedValue),
        int.Parse(ddlMonths.SelectedValue),
        int.Parse(ddlDays.SelectedValue),
        int.Parse(ddlNumSCs.SelectedValue),
        txtDateFrom.Text,
        txtDateTo.Text,
        tradeGrades,
        executionGrades,
        int.Parse(txtMinProfitPips.Text),
        int.Parse(txtMaxProfitPips.Text));

    chtMyRepeatedChart.DataBind();
}

Итак, я хочу заменить DB.MyRepeatedCall, chtMyRepeatedChart и передать их в качестве параметров универсальной функции. Это возможно? В моей форме много диаграмм, которые принимают одинаковое количество параметров.

Спасибо

UPDATE Следуя решению Фредерика, я сделал это:

private delegate IEnumerable<DataTable> GetDataSource(
    int TradeType,
    string RepeatedTrades,
    string Side,
    string TradeSetup,
    DataTable symbols,
    string ChartTimeFrame,
    int Hour,
    int Year,
    int Month,
    int Day,
    int NumSCs,
    string DateFrom,
    string DateTo,
    DataTable TradeGrades,
    DataTable ExecutionGrades,
    int MinProfitPips,
    int MaxProfitPips);

private void PopulateControl(Chart chart, GetDataSource getDataSource)
{
    //DBUtil DB = new DBUtil();
    DataTable symbols = GetSelectedItems("symbol", listSymbols);
    DataTable tradeGrades = GetSelectedItems("tradeGrade", listTradeGrades);
    DataTable executionGrades = GetSelectedItems("executionGrade", listExecutionGrades);

    chart.DataSource = getDataSource(
        int.Parse(ddlTradeTypes.SelectedValue),
        ddlRepeatedTrades.SelectedValue,
        radSide.SelectedValue,
        ddlTradeSetups.SelectedValue,
        symbols,
        ddlChartTimeFrames.SelectedValue,
        int.Parse(ddlHours.SelectedValue),
        int.Parse(ddlYears.SelectedValue),
        int.Parse(ddlMonths.SelectedValue),
        int.Parse(ddlDays.SelectedValue),
        int.Parse(ddlNumSCs.SelectedValue),
        txtDateFrom.Text,
        txtDateTo.Text,
        tradeGrades,
        executionGrades,
        int.Parse(txtMinProfitPips.Text),
        int.Parse(txtMaxProfitPips.Text));

    chart.DataBind();        
}       

Я вызываю функцию с этой командой:

PopulateControl (chtEquityCurve, DB.GetAccountBalances());

Я получаю эту ошибку в intellisense: No overload for method 'GetAccountBalances' takes 0 arguments.

Ответы [ 4 ]

6 голосов
/ 10 декабря 2010

Сначала создайте тип делегата (обычно я рекомендую людям использовать один из доступных Func делегатов, но они поддерживают только до 16 входных параметров, у вас их 18). Дайте ему соответствующее имя и определите все входные параметры, чтобы они имели правильный тип и описательные имена. Заставьте делегата вернуть IEnumerable<T>:

public delegate IEnumerable<WhateverTypeIsReturned> GetDataSource(int firstParam, [...]);

Затем измените PopulateMyRepeatedControl так, чтобы оно выглядело так:

private void PopulateMyRepeatedControl(Chart chart, GetDataSource getDataSource)
{
    DBUtil DB = new DBUtil();
    DataTable symbols = GetSelectedSymbols();
    DataTable tradeGrades = GetSelectedTradeGrades();
    DataTable executionGrades = GetSelectedExecutionGrades();        

    chart.DataSource = getDataSource (
        int.Parse(txtStartBalance.Text),
        int.Parse(ddlTradeTypes.SelectedValue),
        ddlRepeatedTrades.SelectedValue,
        radSide.SelectedValue,
        ddlTradeSetups.SelectedValue,
        symbols,
        ddlChartTimeFrames.SelectedValue,
        int.Parse(ddlHours.SelectedValue),
        int.Parse(ddlYears.SelectedValue),
        int.Parse(ddlMonths.SelectedValue),
        int.Parse(ddlDays.SelectedValue),
        int.Parse(ddlNumSCs.SelectedValue),
        txtDateFrom.Text,
        txtDateTo.Text,
        tradeGrades,
        executionGrades,
        int.Parse(txtMinProfitPips.Text),
        int.Parse(txtMaxProfitPips.Text));

    chart.DataBind();
}

Когда вы вызываете метод, просто передайте диаграмму и метод, который будет использоваться для сбора данных:

PopulateMyRepeatedControl(oneChart, OneDataCollectionMethod);
PopulateMyRepeatedControl(anotherChart, AnotherDataCollectionMethod);

Конечно, TheDataCollectionMethod должен иметь правильную подпись, иначе код не скомпилируется.

Обновление
Относительно вашего обновления; обратите внимание, что вы хотите передать метод в качестве аргумента, а не вызывать его:

PopulateControl (chtEquityCurve, DB.GetAccountBalances);

Обратите внимание, что после имени метода нет ни одного парантеза.

1 голос
/ 10 декабря 2010

что-то вроде ниже

PopulateMyRepeatedControl(Chart c , Func<List<List<T>>>  actionToBeCalled)  
1 голос
/ 10 декабря 2010

Я думаю, вам следует подумать об использовании некоторых концепций ООП, а не о параметризации имени метода. Поскольку у вас есть метод, который принимает параметры, которые фактически являются элементами управления, подумайте о том, чтобы разделить его на разные классы.

Сначала вы должны подумать о перефакторинге кода, потому что у одного метода слишком много параметров. Вы можете инкапсулировать все параметры в класс как

public class RepeatedCallParameters
{
   public string StartBalance{get;set;}

   ...

   ...
}

Тогда у вас может быть абстрактный класс со всеми этими параметрами и метод PrepareRepeatedCallParameters ()

public abstract class ChartProperties : Page
{
    protected abstract int StartBalance {get;}

    public RepeatedCallParameters PrepareRepeatedCallParameters()
    {
         RepeatedCallParameters p = new RepeatedCallParamters();
         p.StartBalance = StartBalance;
         return p;  
    }
}

Тогда

Вы можете реализовать этот класс на странице

public class YourPage: ChartProperties
{
   protected override int StartBalance
   {
     get {return int.Parse(txtStartBalance.Text);} 
   }

   //All properties
   ..

   private void BindChartData()
   {
      RepeatedCallParameter p  = PrepareRepeatedCallParameters();
      Chart.DataSource = DB.RepeatedCall(p);
      Chart.DataBind();   
   }
}

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

0 голосов
/ 10 декабря 2010

Рассмотрите возможность использования делегатов, которые можно рассматривать как указатель на типобезопасную функцию.Делегаты состоят из типа делегата и экземпляра делегата.Я бы порекомендовал использовать встроенные универсальные типы делегатов Action и Func.Действие не имеет типа возврата, Func делает.

public void MyMethod(Func<int, bool> predicate)
{
  if (predicate(5))
  {
    // true
  }
  else
  {
    // false
  }
}

// To call MyMethod, pass a delegate instance (here we are using a lambda expression)
MyMethod(x => x > 5);

Экземпляр делегата вызывается из MyMethod (в качестве параметра предиката), и из-за используемой логики, если значение равно 5, будет возвращено значение false, в противном случае любое значение больше 5 будет иметь значение true.быть возвращенным.Вы можете увидеть, как логика предиката отделена от метода MyMethod, что делает MyMethod повторно используемым для любой части логики.

Обратите внимание, что последний универсальный тип, используемый в Func, является типом возврата, Action не имеет типов возврата,Оба типа делегатов принимают до 16 параметров, но вы, возможно, захотите подумать о своем дизайне, если вам нужно столько!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...