从模型中获取数据注释属性

我想创建自定义客户端validation器,但我想通过业务逻辑层的Data Annotations属性定义validation规则。 如何在运行时访问模型validation属性?

我想写’generator’,它会转换这段代码:

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

输出:

 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() .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()) { var minLength = property.Attributes .OfType() .FirstOrDefault(a => a.Name == "MinLength"); var required = property.Attributes .OfType() .FirstOrDefault(a => a.Name == "Required"); var koAttributes = new List(); if (minLength != null) koAttributes.Add("minLength: " + minLength.Value); if (required != null) koAttributes.Add("required: true"); #> <#= property.Name #>: ko.observable().extend({<#= String.Join(", ", koAttributes) #>}), <# } #> }