سؤال

لقد واجهنا اليوم مشكلة بسيطة للغاية والتي أصبحت أكثر بساطة بسبب المسندات العزيزة.كان لدينا نوع من سجل الأحداث وأردنا تصفيته من جانب العميل (نماذج Windows) باستخدام قائمة المعايير.لقد بدأنا بتنفيذ التصفية حسب عدد من الفئات.

private List<Events> FilterEventsByCategory(List<Events> events,
                                        List<Category> categories) 
{
  return events.FindAll(ev => 
      categories.Exists(category => category.CategoryId==ev.CategoryId)); 
}

والخطوة التالية هي تنفيذ اثنين من المرشحات الأخرى.هل تعرف طريقة لطيفة لتعميم هذه الأمور ربما بطريقة ما لعدم الاضطرار إلى كتابة طريقة واحدة لكل مرشح؟أو على الأقل طريقة نظيفة للحصول على قائمة ديناميكية من المرشحات التي نريد تطبيقها في وقت واحد.

لا يزال العملاء يستخدمون الإصدار 3.0، لذا لا يوجد LINQ.

تحديث:لقد واجهت صعوبة في تحديد من الذي يجب أن أعطيه الفضل في الحل الذي قدمته.كان لدى مارك بعض الأفكار الرائعة وهو جيد حقًا في شرحها.على الأرجح كنت سأحصل على إجابتي منه لو أنني شرحت مشكلتي بشكل أفضل قليلاً.في نهاية المطاف، كانت فئة التصفية العامة التي قدمها cmartin هي التي أوصلتني إلى المسار الصحيح.يمكن العثور على فئة التصفية المستخدمة أدناه في إجابة cmartins وفئة المستخدم التي يمكنك أن تحلم بها بنفسك.

var categoryFilter = new Filter<Event>(ev => categories.Exists(category => category.CategoryId == ev.CategoryId));
var userFilter = new Filter<Event>(ev => users.Exists(user => user.UserId == ev.UserId));

var filters = new List<Filter<Event>>();
filters.Add(categoryFilter);
filters.Add(userFilter);

var eventsFilteredByAny = events.FindAll(ev => filters.Any(filter => filter.IsSatisfied(ev)));
var eventsFilteredByAll = events.FindAll(ev => filters.All(filter => filter.IsSatisfied(ev)));
هل كانت مفيدة؟

المحلول

إليك عينة بدائية للغاية من حيث سأبدأ.

internal class Program
{
    private static void Main()
    {
        var ms = new Category(1, "Microsoft");
        var sun = new Category(2, "Sun");

        var events = new List<Event>
                         {
                             new Event(ms, "msdn event"),
                             new Event(ms, "mix"),
                             new Event(sun, "java event")
                         };

        var microsoftFilter = new Filter<Event>(e => e.CategoryId == ms.CategoryId);

        var microsoftEvents = FilterEvents(events, microsoftFilter);

        Console.Out.WriteLine(microsoftEvents.Count);
    }

    public static List<Event> FilterEvents(List<Event> events, Filter<Event> filter)
    {
        return events.FindAll(e => filter.IsSatisfied(e));
    }
}

public class Filter<T> where T: class
{
    private readonly Predicate<T> criteria;

    public Filter(Predicate<T> criteria)
    {
        this.criteria = criteria;
    }

    public bool IsSatisfied(T obj)
    {
        return criteria(obj);
    }
}

public class Event
{
    public Event(Category category, string name)
    {
        CategoryId = category.CategoryId;
        Name = name;
    }

    public int CategoryId { get; set; }
    public string Name { get; set; }
}

public class Category
{
    public Category(int categoryId, string name)
    {
        CategoryId = categoryId;
        Name = name;
    }

    public string Name { get; set; }
    public int CategoryId { get; set; }
}

نصائح أخرى

إعادة "لذا لا يوجد LINQ" - هل نظرت إليها لينكبريدج؟نظرًا لأنك تستخدم C# 3.0، فسيكون هذا مثاليًا...

أخشى أن السؤال الرئيسي، أنا لا أفهم تماما ما تحاول القيام به وما الذي تحاول تجنبه - هل يمكنك التوضيح على الإطلاق؟ولكن إذا كنت تستخدم أسلوب LINQBridge، فيمكنك دمج المرشحات باستخدام المتعاقبة .Where() المكالمات.

أحد تفسيرات السؤال هو أنك لا تريد الكثير من طرق التصفية - لذا ربما تقوم بتمرير واحد أو أكثر من المسندات الإضافية إلى الطريقة - بشكل أساسي كـ Func<Event, Func<Category, bool>> - أو في حدود 2.0 خالصة، أ Converter<Event, Predicate<Category>>:

private static List<Events> FilterEvents(
    List<Events> events,
    List<Category> categories,
    Converter<Events, Predicate<Category>> func)
{
    return events.FindAll(evt =>
        categories.Exists(func(evt)));
}

والذي يتم استخدامه بعد ذلك (ليكون على النحو الوارد أعلاه) على النحو التالي:

var result = FilterEvents(events, categories,
      evt => category => category.CategoryId==evt.CategoryId);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top