如何使这些方法泛型

本文关键字:泛型 方法 何使这 | 更新日期: 2023-09-27 18:08:52

我有一些字典类型都是

Dictionary<Guid, string>

我有一些功能基本上做同样的事情但使用不同的参数过滤不同的东西。下面是几个示例方法

private IQueryable<SomeClass> FilterContacts(Filter filter,
        IQueryable<SomeClass> query)
    {
        if (filter.Contacts != null && filter.Contacts.Any())
        {
            result = result.Where(x => filter.Contacts.Contains(x.ContactID));
        }
        return result;
    }
private IQueryable<SomeClass> FilterSomethingElse(Filter filter,
        IQueryable<SomeClass> query)
    {
        if (filter.SomethingElse != null && filter.SomethingElse.Any())
        {
            result = result.Where(x => filter.SomethingElse.Contains(x.SomethingElseID));
        }
        return result;
    }

所以它们所有这些方法共享相同的结构,但在过滤器和where子句中使用不同的属性。有没有办法让它足够通用,让我只用一个方法来做这个?

如何使这些方法泛型

下面的解决方案使用委托作为参数注入一些必要的逻辑,使方法更泛型。

private IQueryable<SomeClass> FilterCommon(IQueryable<SomeClass> query
    , Filter filter
    , Func<Filter, Dictionary<Guid, string>> getDictionary
    , Func<SomeClass, Guid> getKey)
{
    IQueryable<SomeClass> result = null;
    Dictionary<Guid, string> commonDictionary = getDictionary(filter);
    if (commonDictionary != null && commonDictionary.Any())
    {
        result = query.Where(x => commonDictionary.ContainsKey(getKey(x)));
    }
    return result;
}

我不认为Filter参数是必要的,所以它可以简化为:

private IQueryable<SomeClass> FilterCommon(IQueryable<SomeClass> query
    , Dictionary<Guid, string> commonDictionary
    , Func<SomeClass,Guid> getKey)
{
    IQueryable<SomeClass> result = null;
    if (commonDictionary != null && commonDictionary.Any())
    {
        result = query.Where(x => commonDictionary.ContainsKey(getKey(x)));
    }
    return result;
}

用法:

//Initializing a few things first...
Filter myFilter = new Filter();
IQueryable<SomeClass> query = new Queryable();//Just a generated type
//This is for my first example from above
FilterCommon(query, myFilter, x => x.Contacts, x => x.ContactID);
//Second example without filter parameter
FilterCommon(query, myFilter.Contacts, x => x.ContactID);
FilterCommon(query, myFilter.SomethingElse, x => x.SomethingElseID);

在这种情况下,策略模式似乎是合适的。

策略模式允许您定义一系列可在运行时选择的可互换算法。要定义你的算法,你可以这样做:

public interface IFilterStrategy<T> 
{
    IQueryable<T> Filter(Filter filter, IQueryable<T> query);
}
public class FilterContacts : IFilterStrategy<SomeClass>
{
     public IQueryable<T> Filter(Filter filter, IQueryable<T> query)
     {
        if (filter.Contacts != null && filter.Contacts.Any())
        {
            result = result.Where(x => filter.Contacts.Contains(x.ContactID));
        }
        return result;
     }
}

public class FilterSomethingElse : IFilterStrategy<SomeClass>
{
     public IQueryable<T> Filter(Filter filter, IQueryable<T> query)
     {
        if (filter.SomethingElse != null && filter.SomethingElse.Any())
        {
            result = result.Where(x => filter.SomethingElse.Contains(x.SomethingElseID));
        }
     }
}

如何实现它取决于类的设计和预期用途。其中一些实现是常见的:

  1. 在运行时向构造函数中注入一个或多个策略
  2. 允许类的公共方法调用者传递一个IFilterStrategy<SomeClass>实例
  3. 维护IFilterStrategy<SomeClass>类型的私有字段,使用私有set()方法进行切换

在任何情况下,您将在实际类中维护单个Filter()方法,该方法将使用指定的策略模式类。