Передайте общий делегат как параметр метода в С#

У меня есть это объявление делегата:

public delegate IEnumerable<T> SearchInputTextStrategy<T, U>(string param);

Предположим, я создал здесь новый делегат SearchInputTextStrategy и назвал его MyDelegate.

это объявление моего метода:

public void BindElements<T, TDisplayProperty,TSortProperty>
(
       IEnumerable<T> dataObjects,
       Func<T, TDisplayProperty> selectorDisplayMember,
       Func<T, TSortProperty> selectorSortMember,
       string delimiter,
       // 1.) how to declare the delegate here as parameter ??
)
{
    // pass here the delegate to a private field to save it
    // 2.) how can I do that?

}

Как я могу сделать 1.) и 2.)? :-)

ОБНОВЛЕНИЕ 2:

Хорошо, вот что я сделал до сих пор:

public class SearchProvider<T>
    {
        public delegate IEnumerable<T> SearchInputTextStrategy<T>(string param);    

        public SearchInputTextStrategy<T> SearchStrategy { get; set; }

        public T TypedValue
        {
            get
            {
                return (T)Convert.ChangeType(SearchStrategy, typeof(T));
            }
        }
    }

Пользовательский контроль:

 public delegate IEnumerable<T> SearchInputTextStrategy<T>(string param);

 public void BindElements<T, TDisplayProperty,TSortProperty>
        (
            IEnumerable<T> dataObjects,
            Func<T, TDisplayProperty> selectorDisplayMember,
            Func<T, TSortProperty> selectorSortMember,
            string delimiter,
            SearchInputTextStrategy<T> searchStrategy
        )
        { 
               /// assign the searchStrategy to the SearchProvider class 
            var sp = new SearchProvider<T>();
                sp.SearchStrategy = searchStrategy  // DOES NOT WORK !!!     
        }

Пожалуйста, прочтите также мои комментарии в Кодексе. Чего я хочу добиться, так это передать делегату searchProvider, чтобы сохранить его где-нибудь... Код, который я пишу здесь, я понимаю до 50%, поэтому, пожалуйста, потерпите меня. Универсальные методы для меня новы, хотя я использую общий список в течение длительного времени; п

ОБНОВЛЕНИЕ 2:

открытый частичный класс MainWindow: Window { открытый делегат IEnumerable SearchInputTextStrategy (параметр строки);

    private SearchInputTextStrategy<ICustomer> _strategy;

    public MainWindow()
    {
        InitializeComponent();            

        IEnumerable<ICustomer> customers = DataService.GetCustomers();                  

        _strategy = new SearchInputTextStrategy<ICustomer>(SearchCustomers);           


        ElementUserControl.BindElements(customers, c => c.FirstName, c => c.SortId, ";", _strategy);

namespace ElementTextBoxV2
{      

        public partial class MainWindow : Window
        {
            public delegate IEnumerable<ICustomer> SearchInputTextStrategy<ICustomer>(string param);

            private SearchInputTextStrategy<ICustomer> _strategy;

            public MainWindow()
            {
                InitializeComponent();            

                IEnumerable<ICustomer> customers = DataService.GetCustomers();                  

                _strategy = new SearchInputTextStrategy<ICustomer>(SearchCustomers);           


                ElementUserControl.BindElements(customers, c => c.FirstName, c => c.SortId, ";", _strategy);

                IEnumerable<ICustomer> selectedElements =  ElementUserControl.SelectedElements<ICustomer>();
            }

            // Just a Test-Methode to assure the delegate works
            public IEnumerable<ICustomer> SearchCustomers(string param)
            {
                IEnumerable<ICustomer> foundCustomers = new List<ICustomer>();
                return foundCustomers;
            }         
        }
    }

Сценарий таков, что пользователь поместил TextBoxUserControl в MainWindow, и ему нужно передать делегат, указывающий на searchMethod. Я реализовал это с помощью метода SearchCustomers_Method. Проблема в том, что С# не может решить это:

    Error   1   The best overloaded method match for 'ElementTextBoxV2.ElementsView.BindElements<ElementTextBoxV2.ICustomer,string,int>(System.Collections.Generic.IEnumerable<ElementTextBoxV2.ICustomer>, System.Func<ElementTextBoxV2.ICustomer,string>, System.Func<ElementTextBoxV2.ICustomer,int>, string, ElementTextBoxV2.Provider.SearchInputTextStrategy<ElementTextBoxV2.ICustomer>)' has some invalid arguments

Error   2   Argument 5: cannot convert from 'ElementTextBoxV2.MainWindow.SearchInputTextStrategy<ElementTextBoxV2.ICustomer>' to 'ElementTextBoxV2.Provider.SearchInputTextStrategy<ElementTextBoxV2.ICustomer>'    

Ты видишь проблему? В любом случае Пользователь должен передать делегат с тем же определением, что и метод BindElements!


person Elisabeth    schedule 28.11.2010    source источник


Ответы (2)


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

public void BindElements<T, TDisplayProperty,TSortProperty>
(
    IEnumerable<T> dataObjects,
    Func<T, TDisplayProperty> selectorDisplayMember,
    Func<T, TSortProperty> selectorSortMember,
    string delimiter,
    SearchInputTextStrategy<T, TDisplayProperty> searchStrategy
)

Я только догадался о том, какими должны быть аргументы типа - вы на самом деле не сказали, что вы хотите, чтобы параметр представлял.

Вы не сможете легко иметь поле нужного типа в своем классе, потому что сам класс не знает задействованных параметров типа. Возможно, вам действительно следует сделать свой класс универсальным или создать другой класс, способный правильно обрабатывать делегаты. Без какой-либо дополнительной информации очень трудно понять, что именно.

person Jon Skeet    schedule 28.11.2010
comment
Бьюсь об заклад, что параметр второго типа для делегата должен быть TSortProperty. Но это всего лишь предположение, как и ваше - person alpha-mouse; 28.11.2010
comment
@Jon и альфа-мышь: о нет, параметр второго типа не имеет ничего общего с TSortProperty или TDisplayProperty, это просто строка, которая передается делегату, который служит шаблоном поиска в базе данных. - person Elisabeth; 29.11.2010
comment
@Jon один...: цитата: Странно, что ваша SearchInputTextStrategy имеет два параметра типа, но на самом деле использует только один... ДВА? ну, это строка параметров и возвращаемое значение T, НЕ? - person Elisabeth; 29.11.2010
comment
@Lisa: Нет, параметры type: T и U. Вы используете T (для возвращаемого типа), но никогда не U. Почему вы вообще включили U в объявление делегата? - person Jon Skeet; 29.11.2010
comment
@Jon, забудь о U, извините, это просто => публичный делегат IEnumerable‹T› SearchInputTextStrategy‹T›(string param); Хорошо, Джон, допустим, я создаю общедоступный класс SearchProvider‹T›, я мог бы даже использовать универсальное свойство, так можно ли было бы сохранить делегата в поле? ПРОБЛЕМА сейчас в том, что тип SearchInputTextStrategy нигде НЕ ИЗВЕСТЕН... - person Elisabeth; 29.11.2010
comment
@Lisa: Хорошо, так проще. Вы говорите, что тип SearchInputTextStrategy нигде НЕ ИЗВЕСТЕН, но это публичный делегат. Я не вижу, в чем проблема. Вы можете сохранить его в поле типа SearchInputTextStrategy<T> в файле SearchProvider<T>. - person Jon Skeet; 29.11.2010
comment
Я обновил свой первоначальный вопрос образцом кода, пожалуйста, проверьте это, Джон, спасибо и спокойной ночи :) - person Elisabeth; 29.11.2010
comment
@Lisa: НЕ РАБОТАЕТ - не совсем подходящее описание того, что не так, поскольку вы ничего не указали о SearchProvider<T>. Если вы сделаете SearchProvider<T>.SearchStrategy свойством типа SearchInputTextStrategy<T>, это должно работать нормально. - person Jon Skeet; 29.11.2010
comment
ах, я не мог устоять ;-) да, извините, вы правы, это правильное сообщение об ошибке моего нового обновленного кода: Ошибка 11 Невозможно неявно преобразовать тип «UserControlElementsView.SearchInputTextStrategy‹T›» в «Provider.SearchProvider‹T›.SearchInputTextStrategy‹ В чем я ошибаюсь? - person Elisabeth; 29.11.2010
comment
@Lisa: Похоже, вы объявили делегата в двух разных местах. Не делай этого. Объявите его один раз, возможно, на уровне пространства имен (т.е. не внутри какого-либо другого типа). - person Jon Skeet; 29.11.2010
comment
да, я объявил делегата на 2 места. Ах, я могу объявить на уровне пространства имен круто, никогда раньше этого не видел, нужно проверить, как это делается ;-) cu latesssss.... - person Elisabeth; 29.11.2010
comment
@Jon хорошо, я поместил делегата над объявлением класса в области пространства имен, теперь это работает! и я удаляю 2-е объявление. Я снова обновил начальный пост с последним вопросом :) - person Elisabeth; 29.11.2010
comment
хорошо, хорошо, я задам последнюю задачу в дополнительном вопросе, чтобы вы снова получили баллы ;P Эй, и я обязательно куплю вашу новую книгу прямо сейчас! - person Elisabeth; 29.11.2010
comment
Хорошо, я решил последнюю проблему, поместив конкретный делегат в пространство имен также MainWindow: открытый делегат IEnumerable‹ICustomer› SearchInputTextStrategy‹ICustomer›(string param); :) а теперь я заказал вашу книгу :P - person Elisabeth; 29.11.2010
comment
@Lisa: Круто - надеюсь, тебе понравится :) - person Jon Skeet; 29.11.2010

person    schedule
comment
Эй, Дэвид, почему ты использовал TDisplayProperty, а не строку? И это не будет работать => SearchInputTextStrategy как поле, потому что его тип не известен - person Elisabeth; 29.11.2010