как использовать готовый делегат функции в QueryAsync?

#c# #sql #.net #sql-server #dapper

#c# #sql #.net #sql-сервер #dapper

Вопрос:

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

Мой делегат функции

 private Func<Authors, AuthorInPrintingEditions, PrintingEditions, Authors> _relationDelegate =
        (Authors authors, AuthorInPrintingEditions relation, PrintingEditions printingEdition) =>
        {
            if (!_dictionaryResult.ContainsKey(authors.Id))
            {
                _dictionaryResult.Add(authors.Id, new Authors()
                {
                    Id = authors.Id,
                    Name = authors.Name,
                    AuthorInPrintingEditions = printingEdition == null
                        ? new List<AuthorInPrintingEditions>()
                        : new List<AuthorInPrintingEditions>()
                        {
                            new AuthorInPrintingEditions()
                            {
                                PrintingEdition = printingEdition
                            }
                        }
                });
            }
            else
            {
                if (printingEdition != null)
                {
                    _dictionaryResult[authors.Id].AuthorInPrintingEditions.Add(new AuthorInPrintingEditions()
                    {
                        PrintingEdition = printingEdition
                    });
                }
            }

            return authors;
        };
 

Мой метод, когда я хочу его использовать

         using (var conneсtion = CreateConnection())
        {
            await conneсtion.QueryAsync<Authors, AuthorInPrintingEditions, PrintingEditions, Authors>(query,
                (authors, authorInPrintingEditions, printingEdition), <--- in this row I want use delegate
                new { skip = skip, pageSize = pageSize }, splitOn: "Id,AuthorId,Id");

            return _dictionaryResult.Values.ToList();
        }
 

Я не понимаю, как передать ему параметры и возможно ли это вообще, или все равно будет проще скопировать и вставить

Комментарии:

1. В этой строке просто поместите _relationDelegate .

2. Один из вариантов параметризации вашего повторно используемого делегата — предоставить как делегат, так и параметры в качестве членов экземпляра некоторого класса. Затем, когда вам понадобится этот делегат, создайте экземпляр этого класса, задайте параметры и передайте делегат для запроса async.

3. это все неправильно… верните IEnumerable<AuthorPrintingEditionPair> , затем используйте ToDictionary(...) расширение

4. @Dusan Да, я это сделал, это сработало

Ответ №1:

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

 public class AuthorsMapper
{
    public int Parameter1;
    public string Parameter2;

    public Func<Authors, AuthorInPrintingEditions, PrintingEditions, Authors> Map =>
    // Your existing code that can now use parameters
}
 

И используйте его так:

 var mapper = new AuthorsMapper 
{
    Parameter1 = 742,
    Parameter2 = "House"
};

await conneсtion.QueryAsync<Authors, AuthorInPrintingEditions, PrintingEditions, Authors>
    (query, mapper.Map, ...);
 

Комментарии:

1. Я бы назвал это чем-то другим, чем Delegate .

2. Спасибо, Dapper вызывает эту функцию a Map , поэтому я изменю свой ответ в соответствии с этим.

3. Дайте ему осмысленное имя; что-то вроде PrintingEditionsDelegate или PrintingEditionsMap или AuthorEditionsMap .

4. Тогда Deleagate это также вводит в заблуждение. Поскольку это используется в контексте Dapper , я бы придерживался используемого там именования. Из исходного кода Dapper: Func<TFirst, TSecond, TThird, TReturn> map

5. Это имя параметра, а не имя аргумента. В любом случае, я сказал свое спокойствие.