Как передать универсальный селектор Funcв какой-то метод для того, чтобы выполнить поиск? - PullRequest
2 голосов
/ 26 октября 2019

У меня есть класс с некоторыми полями.

public abstract class RegisteredUser : Transformable //implements interface
{
    protected int id;
    protected bool active;
    protected string name;
    protected string lastName;
    protected string email;
    protected string username;
    protected string password;
    protected int institution;

//OTHER  STUFF FROM  THIS CLASS GO HERE..`
} 
Assistant : RegisteredUser
{
}

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

public static Dictionary<int, Transformable> assistants = null; //this will be filed with objects and their id's

СейчасМое задание - достичь функциональности search для этого консольного приложения. Поскольку все подклассы будут иметь поля из абстрактного класса, пользователь этого приложения должен выбрать поиск для любого объекта Assistant, Professor или Administrator по любому из его полей.

Я бы хотел добиться этого с помощью LINQ/lambdas. Моя идея состоит в том, чтобы создать некоторый универсальный метод, который будет принимать селектор (или некоторое лямбда-выражение), основанный на любом поле, которое ищется.

Я совершенно новичок в LINQ и C # икак правило, в программировании, поэтому я надеюсь, что я не говорю чепухи здесь.

public static List<RegisteredUser> search(Dictionary<int, Transformable> map, 
                                          Func<bool,RegisteredUser> selector, 
                                          Transformable userType)
{
    if (userType is Assistant)
    {
        List<RegisteredUser> list = map.Select(item => (Assistant) item.Value)
                                       .ToList()
                                       .Select(selector)
                                       .ToList();
    }
    //other if/else statements  

    return list;
}

Конечно, строки в Visual Studio красные :) В принципе, я хочу иметь возможность отправлять что-то вроде user => user.Name.Contains("some string which will be entered by the end user")к общей функции.

1 Ответ

3 голосов
/ 26 октября 2019

Вам на самом деле не нужно писать отдельную функцию, чтобы делать то, что вы хотите достичь, все это можно сделать с помощью Linq напрямую:

var users = new Dictionary<int, Transformable>
{
     {0, new Assistant { Name = "Joe" }},
     {1, new Professor { Name = "John" }},
     {2, new Assistant { Name = "Jane" }}
};

var assistants = users.Values.OfType<Assistant>().Where(a => a.Name == "Jane");

assistants - это IEnumerable<Assistant>с именем, равным «Джейн» и будет содержать только 1 запись из словаря выше. Вы можете добавить ToList () в конец этого списка, чтобы создать список альтернативно

Затем вы можете добавить любой предикат, который вы хотите:

var assistants = users.Values.OfType<Assistant>().Where(a => a.Name == "Jane" && a.LastName == "Smith" && a.Active);

Вы можете обернуть вышеупомянутое в функцию, но чтов итоге вы не будете намного короче, чем указано выше.

В качестве метода расширения он будет выглядеть следующим образом:

public static class Extensions
{
    public static IEnumerable<T> Find<T>(this IEnumerable<Transformable> list, Func<T,bool> predicate) where T :Transformable
    {
        return list.OfType<T>().Where(predicate.Invoke);
    }
}

, делая вызов немного короче:

var assistants = users.Values.Find<Assistant>(a => a.Name == "Jane");

Это пример свободного API-шаблона, поэтому вы можете использовать его в цепочке Linq, как и любую другую функцию Linq.

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