我怎样才能使这些方法通用?

时间:2016-09-25 00:09:47

标签: c# generics methods

我所拥有的是一些所有类型的词典

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子句中使用不同的属性。有没有办法使这个足够通用,我可以有一个方法可以做到这一点?

2 个答案:

答案 0 :(得分:4)

以下解决方案使用委托作为参数来注入使该方法更通用所必需的一些逻辑。

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);

答案 1 :(得分:0)

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

策略模式允许您定义一系列可在运行时选择的可互换算法。要定义算法,您可以执行以下操作:

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. 维护一个使用私有set()方法切换的IFilterStrategy<SomeClass>类型的私有字段
  4. 在任何情况下,您都会在实际的类中维护一个使用指定策略模式类的Filter()方法。