简体   繁体   English

字典中存储的C#“匿名”类型的列表

[英]C# “Anonymous” type of List stored inside a Dictionary

I'm coming to the conclusion this may be impossible, but I figured I'd ask here before giving up entirely. 我得出的结论是,这可能是不可能的,但我认为在完全放弃之前我会先问一下。 What I am looking for is something similar to this: 我正在寻找的东西与此类似:

Dictionary<string, List<T>> FilterLists { get; set; }

I want to be able to store any amount of lists that may be needed and then be able to find them by a string Key 'index'. 我希望能够存储可能需要的任何数量的列表,然后能够通过字符串Key'index'找到它们。

The reason I need it like this is because of where this has to be stored due to certain constraints, and it would be impossible to type the List as anything specific because it can't see the object type that I want to put in there. 我之所以需要它,是因为由于某些限制而必须将其存储在何处,并且不可能将List键入为任何特定的东西,因为它看不到我想要放入的对象类型。 Even if I could see the object type, that reduces its re-usability in other projects where what someone might want to put in there could be constructed differently anyway and I am trying to make this as reusable as possible. 即使我可以看到对象类型,也降低了其在其他项目中的可重用性,在该项目中,人们可能想要放置在其中的内容可能会以不同的方式构造,并且我正在尝试使其尽可能可重用。

I had found this post: Declaration of Anonymous types List , but this doesn't quite work with what I'm trying to do. 我发现了这篇文章: 匿名类型声明List ,但这与我尝试做的工作并不完全相同。

Also, this has to go in an Interface class, so it's simply a definition. 另外,这必须放在Interface类中,因此它只是一个定义。

Usage Explanation : This is specifically for use in paginating results in an MVC5 application. 用法说明 :专门用于在MVC5应用程序中对结果进行分页。 The result list is returned, but I also want dropdown filters in certain header columns (like you would see in Excel filtering of columns). 返回了结果列表,但我还希望某些标题列中有下拉过滤器(就像您在Excel的列过滤中看到的那样)。

I am trying to avoid the use of the ViewBag as much as possible for a few reasons. 由于某些原因,我试图尽可能避免使用ViewBag。 I don't like using it. 我不喜欢用它。 My "Pagination" code is in a project known as Common at a level to make it accessible to both my Web project and my Service project (Business Logic layer). 我的“分页”代码在一个名为Common的项目中,其级别可以使我的Web项目和Service项目(业务逻辑层)都可以访问。 The Models and ViewModels I am using are stored in Service, so I can't have Common referencing Service because Service already references Common for the custom IPagedList construct used to define a list of objects that will be paginated. 我正在使用的Models和ViewModels存储在Service中,因此我无法使用Common引用服务,因为Service已经为用于定义将要分页的对象列表的自定义IPagedList构造引用了Common。 IPagedData contains a bunch of properties for filtering, sorting and paginating the result set. IPagedData包含一堆用于过滤,排序和分页结果集的属性。 A LINQ extension (.ToPageList) was created to facilitate these operations on the data. 创建了LINQ扩展名(.ToPageList),以方便对数据进行这些操作。 There are several objects involved with this process, but I will at least post the IPagedData (where I want this dictionary to go). 此过程涉及多个对象,但至少我要发布IPagedData(我希望此字典放到哪里)。

using System.Collections.Generic;

namespace GameKeyExchange.Common.Pagination
{
    public interface IPagedData
    {
        Dictionary<string, List<T>> FilterLists { get; set; }

        /// <summary>
        /// Stores pagination and sort information.
        /// </summary>
        PageSortCriteria Criteria { get; set; }

        /// <summary>
        /// Total number of subsets within the superset.
        /// </summary>
        int PageCount { get; }

        /// <summary>
        /// Total number of objects contained within the superset.
        /// </summary>
        int TotalItemCount { get; }

        /// <summary>
        /// Zero-based index of this subset within the superset.
        /// </summary>
        int PageIndex { get; }

        /// <summary>
        /// One-based index of this subset within the superset.
        /// </summary>
        int PageNumber { get; }

        /// <summary>
        /// Maximum size any individual subset.
        /// </summary>
        int PageSize { get; }

        /// <summary>
        /// Returns true if this is NOT the first subset within the superset.
        /// </summary>
        bool HasPreviousPage { get; }

        /// <summary>
        /// Returns true if this is NOT the last subset within the superset.
        /// </summary>
        bool HasNextPage { get; }

        /// <summary>
        /// Returns true if this is the first subset within the superset.
        /// </summary>
        bool IsFirstPage { get; }

        /// <summary>
        /// Returns true if this is the last subset within the superset.
        /// </summary>
        bool IsLastPage { get; }
    }
}

The code implementation would ideally look like this in my Service: 理想情况下,代码实现在我的Service中将如下所示:

var list = data.ClaimedKeys.Where(m => m.UserId == UserId).Select(m => new ClaimedKeysViewModel()
{
    KeyTypeId = m.GameKey.GameKeyGroup.KeyTypeId,
    PlatformId = m.GameKey.GameKeyGroup.PlatformId,

    Value = m.GameKey.Value,
    KeyType = m.GameKey.GameKeyGroup.KeyType.Name,
    Game = m.GameKey.GameKeyGroup.Game.Name,
    Platform = m.GameKey.GameKeyGroup.Platform.Name,
    Expiration = m.GameKey.GameKeyGroup.Expiration
})

list.FilterLists.Add("KeyTypeFilter", list.Select(m => new List<SelectListModel>()
{
    Value = m.KeyTypeId,
    Text = m.KeyType
});

list.FilterLists.Add("PlatformFilter", list.Select(m => new List<SelectListModel>()
{
    Value = m.PlatformId,
    Text = m.Platform
});

list.OrderBy(string.Format("{0} {1}", sort, order))
    .ToPagedList<ClaimedKeysViewModel>(pageNumber, pageSize);

This way, I can get the list of data to paginate in the service, build my pagination, and also include any number of Filter Lists which gets sent back to the controller. 这样,我可以获取要在服务中进行分页的数据列表,建立分页,还可以包括任意数量的过滤器列表,这些列表将发送回控制器。 The controller receives this: IPageList which is the list of data, including these extra properties for sorting and filtering. 控制器收到以下信息:IPageList,它是数据列表,包括这些用于排序和过滤的额外属性。 The reason they are passed down with the list of data is so that when resorting by clicking a header or changing the page, you know exactly which page you are on and the current status of your sorting for when it fetches each page or resorts. 它们与数据列表一起传递的原因是,当通过单击标题或更改页面进行重新排序时,您确切地知道您所在的页面以及在获取每个页面或重新排序时排序的当前状态。

Otherwise, I have to make a secondary call to the database to build my Filters and send them down as ViewBag objects. 否则,我必须对数据库进行二次调用以构建我的过滤器并将其作为ViewBag对象向下发送。 Also, because the initial View and the Refresh Method (which is used after the initial load for resorting or navigating pages) I have to have the same code in both Methods to build the lists. 另外,由于初始View和Refresh方法(在初始加载后用于重新排序或导航页面之后使用),我必须在两种方法中使用相同的代码来构建列表。 If I can have it in the service method that generates the list, it only has to be done there; 如果可以在生成列表的服务方法中使用它,则只需在此完成; the same method that is already being called in both controller methods anyway. 无论如何,两个控制器方法中都已经调用了相同的方法。

Hopefully that clarifies the use case better. 希望可以更好地阐明用例。

If you don't know the type T at compile time, then why do you need generics in the first place ? 如果您在编译时不知道类型T,那么为什么首先需要泛型?

If you only mean to re-use it in different projects, then add a generic constraint to your interface : 如果您只是想在不同的项目中重用它,那么可以在您的界面中添加一个通用约束:

public interface IFilters<T>
{
    Dictionary<string, List<T>> FilterLists { get; set; }
}

Apart from using a List<object> , it might help to make your interface generic: 除了使用List<object> ,还可以使您的接口通用:

public interface MyInterface<T>
{
  Dictionary<string, List<T>> FilterLists { get; set; }
}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM