C# 如何使这些方法通用?

C# 如何使这些方法通用?,c#,generics,methods,C#,Generics,Methods,我有一些字典都是这种类型的 Dictionary<Guid, string> 字典 我有很多方法,基本上做相同的事情,但使用不同的参数做不同的事情。下面是一些示例方法 private IQueryable<SomeClass> FilterContacts(Filter filter, IQueryable<SomeClass> query) { if (filter.Contacts != null &&a

我有一些字典都是这种类型的

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;
    }
private IQueryable过滤器触点(过滤器过滤器、,
IQueryable查询)
{
if(filter.Contacts!=null&&filter.Contacts.Any())
{
result=result.Where(x=>filter.Contacts.Contains(x.ContactID));
}
返回结果;
}
专用可更换过滤器或铰链(过滤器、,
IQueryable查询)
{
if(filter.SomethingElse!=null&&filter.SomethingElse.Any())
{
result=result.Where(x=>filter.SomethingElse.Contains(x.SomethingElseID));
}
返回结果;
}

因此,所有这些方法共享相同的结构,但在筛选器和where子句中使用不同的属性。有没有一种方法可以让这种方法足够通用,我只需要一种方法就可以做到这一点?

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

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

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

}
公共接口策略
{
IQueryable过滤器(过滤器过滤器、IQueryable查询);
}
公共类筛选器联系人:IFilterStrategy
{
公共IQueryable筛选器(筛选器筛选器、IQueryable查询)
{
if(filter.Contacts!=null&&filter.Contacts.Any())
{
result=result.Where(x=>filter.Contacts.Contains(x.ContactID));
}
返回结果;
}
}
公共类筛选器Somethingelse:IFilterStrategy
{
公共IQueryable筛选器(筛选器筛选器、IQueryable查询)
{
if(filter.SomethingElse!=null&&filter.SomethingElse.Any())
{
result=result.Where(x=>filter.SomethingElse.Contains(x.SomethingElseID));
}
}
}
然后如何实现这一点取决于类的设计和预期用途。其中一些实现是常见的:

  • 在运行时将一个或多个策略注入构造函数
  • 允许类的公共方法的调用方传递
    IFilterStrategy
    实例
  • 维护一个类型为
    IFilterStrategy
    的私有字段,您可以使用private set()方法进行切换

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

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

    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;
    }
    
    private IQueryable过滤器common(IQueryable查询
    ,过滤器
    ,Func getDictionary
    ,Func getKey)
    {
    IQueryable结果=null;
    Dictionary commonDictionary=getDictionary(过滤器);
    if(commonDictionary!=null&&commonDictionary.Any())
    {
    result=query.Where(x=>commonDictionary.ContainsKey(getKey(x));
    }
    返回结果;
    }
    
    我认为过滤器参数不是必需的,因此可以简化为:

    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;
    }
    
    private IQueryable过滤器common(IQueryable查询
    ,字典
    ,Func getKey)
    {
    IQueryable结果=null;
    if(commonDictionary!=null&&commonDictionary.Any())
    {
    result=query.Where(x=>commonDictionary.ContainsKey(getKey(x));
    }
    返回结果;
    }
    
    用法:

    //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);
    
    //先初始化几件事。。。
    过滤器myFilter=新过滤器();
    IQueryable query=new Queryable()//只是一个生成的类型
    //这是我上面的第一个例子
    FilterCommon(查询,myFilter,x=>x.Contacts,x=>x.ContactID);
    //第二个不带过滤器参数的示例
    FilterCommon(查询,myFilter.Contacts,x=>x.ContactID);
    FilterCommon(查询,myFilter.SomethingElse,x=>x.SomethingElseID);
    
    这看起来是策略模式的一个很好的候选。联系人的类型是否都是
    字典
    ?你能不能把它作为一个参数而不是
    Filter-Filter
    ?当然这是有道理的,但是我认为有一种简单的方法可以用一个方法进行过滤,而不是现在有一堆实现IFilterStrategy的类。另外,我会有15个这样的过滤器。@Matthew可能不确定我的问题是否正确,但如果所有的filter.Class都是某种集合,为什么不能传递集合本身并搜索它们或类似的内容:private IQueryable FilterContacts(filter filter,dynamic someClass,string属性){var searchfrom=someClass.GetType().GetProperty(property).GetValue(filter,null);这更像是我在想的。让我看看我是否可以用它来做一些事情。