Eri*_*ips 9 c# generics asp.net-mvc attributes automapper
让我们从一个简单的视图模型开始:
public class MyViewModel
{
public string Value { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
下拉列表可能如下所示:
@Html.DropDownListFor(m => m.Value, Model.Values)
Run Code Online (Sandbox Code Playgroud)
但是,因为下拉列表需要两个值,所以不能使用它:
public class MyViewModel
{
[UIHint("DropDownList")]
public string Value { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
视图包含:
@Html.EditForModel()
Run Code Online (Sandbox Code Playgroud)
因为下拉知道源代码没有固有的方法,直到你从UIHint中驱逐:
public DropDownListAttribute : UIHintAttribute
{
public DropDownListAttribute (string valuesSource)
: base("DropDownList", "MVC")
{
}
}
Run Code Online (Sandbox Code Playgroud)
那么人们可能会喜欢它:
public class MyViewModel
{
[DropDownList("Planets")]
public string PlanetId{ get; set; }
public IEnumerable<SelectListItem> Planets { get; set; }
[DropDownList("Cars")]
public string CarId{ get; set; }
public IEnumerable<SelectListItem> Cars { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是,这并不是真正强类型的,有人重命名其中一个魔术字符串或属性名称而不更改另一个并且它在运行时中断.
一个理论解决方案是创建一个通用属性:
public DropDownListAttribute<TModel, TValue> : UIHintAttribute
{
public DropDownListAttribute (Expression<Func<TModel, TValue> expression)
: base("DropDownList", "MVC")
{
}
}
Run Code Online (Sandbox Code Playgroud)
用法是:
public class MyViewModel
{
[DropDownList<MyViewModel, IEnumerable<SelectListItem>>( m => m.Planets)]
public string PlanetId{ get; set; }
public IEnumerable<SelectListItem> Planets { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是将两者封装到一个类中,ModelBinder可以在post-back上重新创建:
public class DropDownListTemplate
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
public class MyViewModel
{
public DropDownListTemplate Planet { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这在ViewModel,Binding和EditFor/DisplayFor模板中创建了简单性,但是由于我对AutoMapper的有限了解,它在AutoMapper映射到类属性的属性时增加了复杂性.据我所知,我不能简单地说:
public class MyPlanets
{
public string SelectedPlanet { get; set; }
}
Mapper.CreateMap<MyPlanets, MyViewModel>();
Mapper.CreateMap<MyViewModel, MyPlanets>();
Run Code Online (Sandbox Code Playgroud)
有没有一种更简单的方法可以让automapper自动地映射这些值,或者有没有办法创建一个强类型的非泛型属性?
要使属性名称强类型化,您可以使用nameof
C# 6 中引入的属性名称。
nameof
是一个与 类似的表达式typeof
,但它不返回值的类型,而是以字符串形式返回值。
用于获取变量、类型或成员的简单(非限定)字符串名称。当报告代码中的错误、连接模型-视图-控制器 (MVC) 链接、触发属性更改事件等时,您通常希望捕获方法的字符串名称。使用 nameof 有助于在重命名定义时保持代码有效。
public class MyViewModel
{
[DropDownList(nameof(Planets))]
public string PlanetId{ get; set; }
public IEnumerable<SelectListItem> Planets { get; set; }
[DropDownList(nameof(Cars))]
public string CarId{ get; set; }
public IEnumerable<SelectListItem> Cars { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1249 次 |
最近记录: |