2014-08-27 31 views
0

我得出的结论可能是不可能的,但我想我会在完全放弃之前问这里。我所寻找的是类似这样的东西:存储在字典中的C#“匿名”类型的列表

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

我希望能够存储可能需要列出的任何金额,然后可以通过一个字符串键“索引”来找到它们。

我需要这样的原因是由于某些约束条件导致它必须存储在哪里,并且不可能将List列为任何特定对象,因为它无法看到我想要的对象类型放在那里。即使我可以看到对象类型,也会降低其他项目中的可重用性,因为在其他项目中,有人可能想要放在其中的某个项目的构建方式可能会有所不同,我试图尽可能使其具有可重用性。

我发现了这篇文章:Declaration of Anonymous types List,但这并不完全符合我所要做的。

此外,这必须在一个接口类,所以它只是一个定义。

使用说明: 这是专门用于分页MVC5应用程序的结果。返回结果列表,但我也希望在某些标题列中使用下拉筛选器(就像您在Excel的列筛选中看到的那样)。

我想尽量避免使用ViewBag,因为几个原因。我不喜欢使用它。 我的“分页”代码位于一个称为Common的项目中,这个项目可以让我的Web项目和我的Service项目(业务逻辑层)都可以访问它。我正在使用的模型和ViewModel存储在Service中,所以我不能使用Common引用服务,因为Service已经为用于定义将分页的对象列表的自定义IPagedList结构引用Common。 IPagedData包含一组用于筛选,排序和分页结果集的属性。一个LINQ扩展(.ToPageList)被创建来促进数据上的这些操作。这个过程涉及到几个对象,但我至少会发布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; } 
    } 
} 

的代码实现理想的情况是这样的,我服务:

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

这样一来,我可以得到的数据列表中的服务进行分页,建立我的分页,并且还包括任何过滤器列表的数量被发送回控制器。控制器接收到:IPageList是数据列表,包括用于排序和过滤的这些额外属性。他们与数据列表一起传递的原因是,当通过单击标题或更改页面时,您确切知道您处于哪个页面以及您获取每个页面或度假村时的当前排序状态。

否则,我必须对数据库进行辅助调用才能构建过滤器并将其作为ViewBag对象发送。另外,因为初始视图和刷新方法(在初始加载页面后使用它),我必须在两种方法中都有相同的代码来构建列表。如果我可以在生成列表的服务方法中拥有它,那只需在那里完成;无论如何,这两个控制器方法中已经调用过相同的方法。

希望能够更好地阐明用例。

+0

向我们展示你希望如何使用** **那个。顺便说一句,如果你添加一个通用参数'T'到你的界面(或者 - 放弃良好的编译时检查 - 如果你避免泛型 - 所有在一起 - 无类型列表,对象或动态 - 如果列表内部不同'interface')... – 2014-08-27 13:44:23

+4

'List '可以保存匿名类型,但是如果没有反射或其他东西,你不能对它们做很多事情。 '列表'可以容纳它们并允许你输入成员,但是会将很多潜在的问题转移到运行时。我诚实的回答?对于任何问题,这似乎是一个非常糟糕的设计/解决方案。 – 2014-08-27 13:45:18

+1

你会发现这个问题的唯一答案是添加一个类型参数到你的类/接口,正如其他人所说的。这将有助于看到你打算如何使用它。 – Brandon 2014-08-27 13:56:02

回答

0

除了使用List<object>,它可能有助于使你的界面通用:

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

如果你不知道在编译时类型T,那么为什么你需要摆在首位的仿制药?

如果你仅仅意味着在不同项目中重新使用它,然后添加一个通用的限制,以你的接口:

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

也许T在这里使用是错误的。我只是用它作为一个占位符来表示动态的东西,我们不知道在运行时会有什么。接口本身没有提及。我只需要在'List <>'之间插入一些东西,这样当我在代码中的其他地方实现时,我就可以用一个未知的传入对象的List来填充它。 – 2014-08-27 15:13:46

+0

你在这里讨论的两种不同的东西: - 如果你想知道什么是运行时类型,那么使用列表,但我不知道你将如何访问对象,除非使用反射(这不是正确的事情做)。 - 但是,如果你知道对象的类型和编译时间(当你编写代码的时候),并且每个项目都有所不同,那么使用泛型约束是正确的选择 – 2014-08-27 15:16:20

+0

@RobertBurke我会检查你的问题现在编辑,对不起,我以前没有看到它 – 2014-08-27 15:18:23