ちょいと作ってみた。
これをひな形にやっていけばいかなぁ。もっといい方法とかあるよ!って人は教えてください。
ClassDef.ttinclude
とりあえずクラスのメタデータを定義するためのクラス群
<#+ // 名前空間 class NSDef { public string NS { get; set; } public ClassDef[] Classes { get; set; } } // クラスの定義 class ClassDef { public string Name { get; set; } public PropertyDef[] Properties { get; set; } } // プロパティの定義 class PropertyDef { public string Type { get; set; } public string Name { get; set; } public string[] Attributes { get; set; } } #>
ClassGen.ttinclude
NSDefやClassDefやPropertyDefをもとにしてViewModelのクラスを生成する部分。
<# foreach (var n in ns) { #> namespace <#= n.NS #> { using System; using System.ComponentModel.DataAnnotations; <# foreach (var clazz in n.Classes) { #> public partial class <#= clazz.Name #> : WpfApplication15.ViewModelBase { <# foreach (var p in clazz.Properties) { #> private <#= p.Type #> _<#= p.Name #>; <# foreach (var attr in p.Attributes) { #> [<#= attr #>] <# } #> public <#= p.Type #> <#= p.Name #> { get { return _<#= p.Name #>; } set { if (Equals(value, _<#= p.Name #>)) { return; } Validator.ValidateProperty( value, new ValidationContext(this, null, null) { MemberName = "<#= p.Name #>" }); _<#= p.Name #> = value; base.OnPropertyChanged("<#= p.Name #>"); } } <# } #> } <# } #> } <# } #>
MyClasses.ttinclude
ClassDefとかを使ってクラスのメタデータを定義する。
<# var ns = new[] { new NSDef { NS = "WpfApplication15.ViewModels", Classes = new[] { new ClassDef { Name = "PersonViewModel", Properties = new[] { new PropertyDef { Type = "string", Name = "Name", Attributes = new[] { "Required(ErrorMessage=\"だめよ\")" } } } } } } }; #>
Generator.tt
上のファイルをとりまとめて実際に自動生成するファイル。
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #> <#@ include file="ClassDef.ttinclude" #> // <autogenerated /> <#@ include file="MyClasses.ttinclude" #> <#@ include file="ClassGen.ttinclude" #>
実際に生成されるコード
こんな感じのコードが作られます。
// <autogenerated /> namespace WpfApplication15.ViewModels { using System; using System.ComponentModel.DataAnnotations; public partial class PersonViewModel : WpfApplication15.ViewModelBase { private string _Name; [Required(ErrorMessage="だめよ")] public string Name { get { return _Name; } set { if (Equals(value, _Name)) { return; } Validator.ValidateProperty( value, new ValidationContext(this, null, null) { MemberName = "Name" }); _Name = value; base.OnPropertyChanged("Name"); } } } }