我已经开发了一个MVC帮助器来生成显示和可编辑表(需要一个jquery插件来允许在可编辑表中动态添加和删除具有完全回发的行),例如
@Htm.TableDisplayFor(m => m.MyCollection as ICollection)
Run Code Online (Sandbox Code Playgroud)
与属性一起使用的将包括页脚中的总计,添加用于查看和编辑链接的列,为复杂类型呈现超链接等.例如
[TableColumn(IncludeTotals = true)]
Run Code Online (Sandbox Code Playgroud)
我即将在CodeProject上发布它,但在此之前,我想解决一个问题.帮助程序首先ModelMetadata从表达式中获取,检查它是否实现ICollection,然后获取集合中的类型(注意以下代码片段来自SO上的已接受答案,但如下所述,并不完全正确)
if (collection.GetType().IsGenericType)
{
Type type = collection.GetType().GetGenericArguments()[0]
Run Code Online (Sandbox Code Playgroud)
该类型用于生成ModelMetadata表头(表中可能没有任何行)和表体中的每一行(如果某些项是继承类型,具有其他属性,否则会搞乱列布局)
foreach (var item in collection)
{
ModelMetadata itemMetadata = ModelMetadataProviders.Current
.GetMetadataForType(() => item, type);
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是使用IEnumerable,而不是ICollection让.ToList()不需要它的LINQ表达式被调用.
在大多数情况下,IEnumerable工作正常
IEnumerable items = MyCollection.Where(i => i....);
Run Code Online (Sandbox Code Playgroud)
没问题因为.GetGenericArguments()返回一个只包含一种类型的数组.问题是某些查询的'.GetGenericArguments()'返回2种或更多类型,似乎没有逻辑顺序.例如
IEnumerable items = MyCollection.OrderBy(i => i...);
Run Code Online (Sandbox Code Playgroud)
返回[0]集合中的类型,[1]用于排序的类型.
在这种情况下.GetGenericArguments()[0]仍然有效,但是
MyCollection.Select(i => new AnotherItem()
{
ID = i.ID,
Name = 1.Name
}
Run Code Online (Sandbox Code Playgroud)
返回[0]原始集合中的类型和[1]的类型 AnotherItem
所以.GetGenericArguments()[1]我需要为表格渲染AnotherItem.
我的问题是,是否有一种可靠的方法使用条件语句来获取表格所需的类型?
从我到目前为止的测试中,.GetGenericArguments().Last()除了使用时,在所有情况下都使用了工作,OrderBy()因为排序键是最后一种类型.
到目前为止我尝试过的一些事情包括忽略值类型的类型(通常会出现这种情况OrderBy(),但OrderBy()查询可能会使用a string(可以检查),甚至更糟糕的是,重载==,<和>的类运算符(在这种情况下,我无法分辨哪个是正确的类型),并且我无法找到测试集合是否实现的方法IOrderedEnumerable.
小智 5
解决(使用克里斯·辛克莱尔发表的评论)
private static Type GetCollectionType(IEnumerable collection)
{
Type type = collection.GetType();
if (type.IsGenericType)
{
Type[] types = type.GetGenericArguments();
if (types.Length == 1)
{
return types[0];
}
else
{
// Could be null if implements two IEnumerable
return type.GetInterfaces().Where(t => t.IsGenericType)
.Where(t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.SingleOrDefault().GetGenericArguments()[0];
}
}
else if (collection.GetType().IsArray)
{
return type.GetElementType();
}
// TODO: Who knows, but its probably not suitable to render in a table
return null;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2102 次 |
| 最近记录: |