即使我知道这些库已经存在,我决定创建一个MVC5 HtmlHelper库来从模型生成表。重点是在C#中练习(实际学习)关于泛型和lambdas。
我希望我的库能够使用如下语法生成HTML表:
@Html.DisplayTable(model => model.ListTest).Render()
此时,上述代码完美无缺。但是当我试图添加方法exclude
时,一切都出错了......这就是我对lambdas和delegate的理解有多差的地方。 (它实际上是我第一次编写将委托作为参数的代码)
以下是我希望拨打电话的方式
@Html.DisplayTable(model => model.ListTest).Exclude(l => l.Col1).Render()
然后这是我提供给我的视图的模型
public class TestViewModel
{
public List<RowViewModel> ListTest { get; set; }
}
其中RowViewModel
定义如下
public class RowViewModel
{
public string Col1 { get; set; } = "Col1Value";
public string Col2 { get; set; } = "Col2Value";
public string Col3 { get; set; } = "Col3Value";
}
我的助手
public static class TableHelpers
{
public static HtmlTable<TValue> DisplayTable<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression) where TValue : IList
{
Func<TModel, TValue> deleg = expression.Compile();
var result = deleg(helper.ViewData.Model);
return new HtmlTable<TValue>(result);
}
}
我的“图书馆逻辑”
public class HtmlTable<TValue> where TValue : IList
{
private TValue _inputModel;
private readonly TableViewModel _outputViewModel = new TableViewModel();
public HtmlTable(TValue model)
{
Init(model);
}
public HtmlTable<TValue> Init(TValue model)
{
if(model.Count == 0)
throw new ArgumentException("The list must not be empty");
_inputModel = model;
UpdateViewModel();
return this;
}
private void UpdateViewModel()
{
var subType = _inputModel.GetContainedType();
var properties = subType.GetProperties();
_outputViewModel.Header = properties.Select(p => p.Name).ToList();
_outputViewModel.Rows = new List<List<string>>();
foreach (var row in _inputModel)
{
var values = _outputViewModel.Header.Select(col => subType.GetProperty(col).GetValue(row, null).ToString()).ToList();
_outputViewModel.Rows.Add(values);
}
}
public HtmlTable<TValue> Exclude<TSubValue>(Expression<Func<TValue, TSubValue>> expression)
{
Func<TValue, TSubValue> deleg = expression.Compile();
var result = deleg(_inputModel);
return this;
}
}
如果我要向我的助手指定行的模型,我有点想知道应该怎么做,例如
@Html.DisplayTable<RowViewModel>(model => model.ListTest).Exclude(l => l.Col1).Render()
但我真的希望能够确定列表中包含的类型以使lambda工作。
所有这一切都没有任何意义,但是从理论的角度来理解lambdas一段时间之后我决定最好停止阅读文章并尝试用它做点什么......
答案 0 :(得分:0)
我找到了解决方案,而且非常简单。
我所要做的就是用TValue
替换Expression<Func<TModel, TValue>> expression
中的IEnumerable<TValue>
并删除where TValue : IList
。
这允许我打电话
@Html.DisplayTable(model => model.ListTest)
无需明确指定任何泛型类型。