8

カスタムクライアント側バリデーターを作成したいが、ビジネスロジックレイヤーでデータ注釈属性を使ってバリデーションルールを定義したい。実行時にモデルの検証属性にアクセスするにはどうすればよいですか?モデルからデータアノテートを取得

私はこのコードを変換れる、 '発電機' を書きたい:

public class LoginModel 
{ 
    [Required] 
    [MinLength(3)] 
    public string UserName { get; set; } 

    [Required] 
    public string Password { get; set; } 
} 

1本に:

var loginViewModel= { 
    UserName: ko.observable().extend({ minLength: 3, required: true }), 
    Password: ko.observable().extend({ required: true }) 
}; 

でもない.csファイルのソースから、もちろん。 =)

多分反射ですか? MSDN:私はこの方法を見つけた

UPD

。しかし、それを使用する方法を理解することはできません。

+0

はい、反射。ほかに何か? –

+1

反射は常にオプションですが、ソースからこれを行うことを避けたい特定の理由はありますか? T4 + EnvDTEはここでは確固たる選択肢のようです。 – decPL

+0

@HenkHolterman私はmvcのソースを読んで、この方法を見つけました:http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper.getunobtrusivevalidationattributes(v=vs.108).aspxそれを使用する方法を理解することはできません。おそらく誰かがリフレクションよりも良いアイデアを持っているでしょうか? =) – letalumil

答えて

13

これは、これを行うにはどのようにユニバーサル方法です:それは出力

をキャッシュすることをお勧めします

var loginViewModel = { 
    UserName: ko.observable().extend({ minLength: 3, required: true}), 
    Password: ko.observable().extend({ required: true}), 
}; 

:出力

string validationModel = GenerateValidationModel<LoginModel>(); 

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 + "};"; 
} 

を使用

+0

まさに私が必要なもの!どうもありがとうございます! – letalumil

3

上記のように、私は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) #>}), 
<# 
    } 
#> 
} 
+1

ありがとう!私はこの非ランタイムソリューションを試してみます:) – letalumil

関連する問題