简体   繁体   English

具有泛型类型的函数中使用的Ordeby(),Where()等

[英]Ordeby(), Where(), etc. used in a function with generic types

I am currently fiddling with generic repositories. 我目前在摆弄通用存储库。 My test application is in C#. 我的测试应用程序在C#中。 I have made a function that prints out all items in particular repository. 我做了一个可以打印出特定存储库中所有项目的函数。 A repository is an input parameter. 存储库是输入参数。 The whole block is at the bottom of this post and currently the function itself looks like this: 整个代码块在本文的底部,当前函数本身如下所示:

static void PrintCollection<T, TKey>(IRepository<T, TKey> repo)
{
    // Error since compiler does not recognizes p.LastName
    //foreach (Person p in repo.GetItems().OrderBy(p => p.LastName)) Console.WriteLine(Convert.ToString(p));
    foreach (T p in repo.GetItems())
        Console.WriteLine(Convert.ToString(p));
}

It's working fine but it's missing things like ordering by particular property in a class, such as LastName in Person or ProductName in Product . 它工作正常,但缺少诸如按类中的特定属性排序的功能,例如Person LastNameProduct ProductName I was wondering if it's possible to send an extra parameter to PrintCollection<T, TKey>(...) and test whether the particular field exists and then order by it. 我想知道是否有可能将额外的参数发送给PrintCollection<T, TKey>(...)并测试特定字段是否存在,然后对其进行排序。 For instance: 例如:

static void PrintCollection<T, TKey, TOrder>(IRepository<T, TKey> repo, TOrder o = default(TOrder))
{
    if (o == default(TOrder))
        foreach (T p in repo.GetItems()) Console.WriteLine(Convert.ToString(p));
    else
        // Order by o
}

At the moment, I don't know what I should use to test the fields and properties against their existance in a class. 目前,我不知道应该使用什么来测试字段和属性是否存在于类中。 And then, how to use them in LINQ and Lambdsa Expression to eg order, sort, filter collections. 然后,如何在LINQ和Lambdsa Expression中使用它们,例如对集合进行排序,排序和过滤。

Thanks 谢谢


Below is a snippet of my code. 以下是我的代码片段。 I cut out unimportant parts. 我删去了不重要的部分。

Main program 主程序

class PeopleRepository : IRepository<Person, string>
{
    private static List<Person> _proxy;

    public PeopleRepository(List<Person> people = null)
    {
        if(people == null) _proxy = Person.GetAllPeople();
        else _proxy = people;
    }

    public IEnumerable<Person> GetItems()
    {
        return _proxy;
    }

    public Person GetItem(string key)
    {
        return _proxy.SingleOrDefault(p => p.ID == key);
    }
}

Interface IRepository 接口IRepository

class ProductsRepository : IRepository<Product, int>
{
    private static List<Product> _proxy;

    public ProductsRepository(List<Product> products = null)
    {
        if (products == null) _proxy = Product.GetAllProducts();
        else _proxy = products;
    }

    public IEnumerable<Product> GetItems()
    {
        return _proxy;
    }

    public Product GetItem(int key)
    {
        return _proxy.SingleOrDefault(p => p.ID == key);
    }
}

Repository for People 人的资料库

 class PeopleRepository : IRepository<Person, string> { private static List<Person> _proxy; public PeopleRepository(List<Person> people = null) { if(people == null) _proxy = Person.GetAllPeople(); else _proxy = people; } public IEnumerable<Person> GetItems() { return _proxy; } public Person GetItem(string key) { return _proxy.SingleOrDefault(p => p.ID == key); } } 

Repository for Products 产品资料库

 class ProductsRepository : IRepository<Product, int> { private static List<Product> _proxy; public ProductsRepository(List<Product> products = null) { if (products == null) _proxy = Product.GetAllProducts(); else _proxy = products; } public IEnumerable<Product> GetItems() { return _proxy; } public Product GetItem(int key) { return _proxy.SingleOrDefault(p => p.ID == key); } } 

Yes, you can, using delegate for selecting order by clause: 是的,您可以使用委托来选择order by子句:

static void PrintCollection<T, TKey, TOrder>(IRepository<T, TKey> repo, 
       Func<T,TOrder> orderBy)
{
    var items = repo.GetItems();
    if (orderBy != null)
        items = items.OrderBy(orderBy);
    foreach (T p in items)
        Console.WriteLine(Convert.ToString(p));
}

you can call it like: 您可以这样称呼它:

PrintCollection(repo, x=>x.Name);

For Where you need argument of type Func<T,bool> and the process is the same as above. 对于Where需要类型的参数Func<T,bool>并且该过程是与上述相同。

Note: If you use ORM like EF, the ORMs need entire expression tree in order to build the SQL statement for the query. 注意:如果使用像EF这样的ORM,则ORM需要整个表达式树,以便为查询构建SQL语句。 As we pass a delegate, so the ordering or filtering does not translate to SQL. 当我们传递委托时,排序或过滤不会转换为SQL。 The ORM loads the data then applies ordering or filtering on it. ORM加载数据,然后对其进行排序或过滤。

If you want to make sure they translate to SQL, the return type must be of type that implements IQueryable and the parameters for the function should change to Expression<Func<T,TOrder>> for orderBy and Expression<Func<T,bool>> for while . 如果要确保将它们转换为SQL,则返回类型必须是实现IQueryable的类型,并且该函数的参数应针对orderByExpression<Func<T,bool>>更改为Expression<Func<T,TOrder>>Expression<Func<T,bool>>while

Suggestion 建议

Define this method as extension for IEnumerable : 将此方法定义为IEnumerable扩展:

public static class IEnumerableExtenstions
{
    static void PrintCollection<T>(this IEnumerable<T> collection)
    {
        foreach (T p in collection)
            Console.WriteLine(Convert.ToString(p));
    }
}

and then you can call it like: 然后可以这样称呼它:

repo.GetItems().Where(x=>x.Age>15).OrderBy(x=>x.Name).PrintCollection();

which is more flexible and natural than defining parameters for each functionality in the function. 这比为函数中的每个功能定义参数更加灵活自然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用属性序列化通用插入、更新等语句? - Using attributes to serialize generic insert, update, etc. statements? C#:通用数学函数(Min、Max 等) - C#: generic math functions (Min, Max etc.) 与不同商店(UserStore,UserEmailStore,UserClaimStore,UserLockoutStore等)一起使用的UserManager - UserManager used with different stores (UserStore, UserEmailStore, UserClaimStore, UserLockoutStore etc.) 如何检查两种类型是否可以比较,总结等? - How to check if two types can be compared, summed etc.? Funcs / Actions / etc应该在哪里 输入代码? - Where should Funcs/Actions/etc. go in code? 用于确定一个月的第一天,一个月的最后一天等的功能。 - Function to determine first day of a month, last day of a month, etc. C#泛型类:如何限制成员函数与特定类型一起使用? - c# generic class: how can I restrict a member function to be used with specific types? 如何获取在数组的方法中使用的泛型类型? - How to get the generic types used in a method in an array? 是否可以将Take(),Skip(),OrderBy()等作为谓词传递给函数? - Is it possible to pass Take(), Skip(), OrderBy() etc. as predicates to a function? 如何为泛型类型重写 function? - How to rewrite function for generic types?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM