从模型中获取数据注释属性
本文关键字:注释 属性 数据 获取 模型 | 更新日期: 2023-09-27 18:37:12
我想创建自定义客户端验证器,但我想通过业务逻辑层的数据注释属性定义验证规则。如何在运行时访问模型验证属性?
我想写"生成器",它将转换此代码:
public class LoginModel
{
[Required]
[MinLength(3)]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
}
进入这个:
var loginViewModel= {
UserName: ko.observable().extend({ minLength: 3, required: true }),
Password: ko.observable().extend({ required: true })
};
但当然不是来自.cs来源。 =)
也许反思?
UPD
我找到了这种方法:MSDN。但是不明白如何使用它。
这是如何执行此操作的通用方法:
private string GenerateValidationModel<T>()
{
var name = typeof(T).Name.Replace("Model", "ViewModel");
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
var validationModel = "var " + name + " = {'n";
foreach (var prop in typeof(T).GetProperties())
{
object[] attrs = prop.GetCustomAttributes(true);
if (attrs == null || attrs.Length == 0)
continue;
string conds = "";
foreach (Attribute attr in attrs)
{
if (attr is MinLengthAttribute)
{
conds += ", minLength: " + (attr as MinLengthAttribute).Length;
}
else if (attr is RequiredAttribute)
{
conds += ", required: true";
}
// ...
}
if (conds.Length > 0)
validationModel += String.Format("'t{0}: ko.observable().extend({{ {1} }}),'n", prop.Name, conds.Trim(',', ' '));
}
return validationModel + "};";
}
用法:
string validationModel = GenerateValidationModel<LoginModel>();
输出:
var loginViewModel = {
UserName: ko.observable().extend({ minLength: 3, required: true}),
Password: ko.observable().extend({ required: true}),
};
缓存输出是个好主意
如上所述 - 我相信 T4 可能值得在这里一试。一个巨大的好处是它不会在运行时执行(尽管它可以,如果你的要求),你可以避免运行时文件生成的所有可能的问题。希望有足够的起点:
<#@ template language="C#" debug="True" hostspecific="true" #>
<#@ output extension="js" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="EnvDTE" #>
<#
var serviceProvider = Host as IServiceProvider;
if (serviceProvider == null)
{
throw new InvalidOperationException("Host is not IServiceProvider");
}
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
if (dte == null)
{
throw new InvalidOperationException("Unable to resolve DTE");
}
var project = dte.Solution.Projects
.OfType<Project>()
.Single(p => p.Name == "ConsoleApplication2");
var model = project.CodeModel
.CodeTypeFromFullName("MyApp.LoginModel")
as CodeClass;
//might want to have a list / find all items matching some rule
#>
var <#= Char.ToLowerInvariant(model.Name[0])
+ model.Name.Remove(0, 1).Replace("Model", "ViewModel") #>= {
<#
foreach (var property in model.Members.OfType<CodeProperty>())
{
var minLength = property.Attributes
.OfType<CodeAttribute>()
.FirstOrDefault(a => a.Name == "MinLength");
var required = property.Attributes
.OfType<CodeAttribute>()
.FirstOrDefault(a => a.Name == "Required");
var koAttributes = new List<String>();
if (minLength != null)
koAttributes.Add("minLength: " + minLength.Value);
if (required != null)
koAttributes.Add("required: true");
#>
<#= property.Name #>: ko.observable().extend({<#=
String.Join(", ", koAttributes) #>}),
<#
}
#>
}