通过T4代码生成自动INotifyPropertyChanged实现?

我正在设置我的新项目,并且想知道如何实现我的ViewModel类确实具有INotifyPropertyChanged支持,而不必亲自手动编码所有属性。

我查看了AOP框架,但我认为他们只会用另一个依赖项炸毁我的项目。

所以我考虑用T4生成属性实现。

设置是这样的:我有一个ViewModel类,它只声明了它的Properties背景变量,然后我使用T4从它生成Property Implementations。

例如,这将是我的ViewModel:

public partial class ViewModel { private string p_SomeProperty; } 

然后T4将遍历源文件并查找名为“p_”的成员声明并生成如下文件:

 public partial class ViewModel { public string SomeProperty { get { return p_SomeProperty; } set { p_SomeProperty= value; NotifyPropertyChanged("SomeProperty"); } } } 

这种方法有一些优点,但我不确定它是否真的有效。 所以我想在StackOverflow上发布我的想法作为一个问题,以获得一些反馈,也许一些建议如何更好/更容易/更安全。

这是Colin Eberhardt关于通过使用EnvDTE直接从Visual Studio检查自定义属性从T4生成依赖属性的一篇精彩文章 。 由于post包含浏览代码节点的简单实用方法,因此将其调整为检查字段并适当生成代码应该不难。

请注意,在VS中使用T4时,不应在自己的程序集上使用Reflection,否则它们将被锁定,您必须重新启动Visual Studio才能重建。

有很多方法可以给这只猫上皮。

我们一直在用PostSharp来注入INotifyProperty样板。 这似乎工作得很好。

话虽如此,T4没有理由不起作用。

我同意Dan的观点,你应该创建OnPropertyChanged的基类实现。

您是否考虑过只使用代码段? 它会为你编写样板文件。 唯一的缺点是,如果您想在以后更改属性名称,它将不会自动更新。

    
propin propin Code snippet for property and backing field with support for INotifyProperty Expansion
type Property type int property Property name MyProperty

它应该肯定有用。

我建议先写一个实现INotifyPropertyChanged的基类,给它一个protected void OnPropertyChanged(string propertyName)方法,使其缓存其PropertyChangeEventArgs对象(每个唯一的属性名称一个 – 每次事件创建一个新对象都没有意义被提出),你的T4生成的类来自这个基础。

要获得需要实现属性的成员,您可以执行以下操作:

 BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; FieldInfo[] fieldsNeedingProperties = inputType.GetFields(flags) .Where(f => f.Name.StartsWith("p_")) .ToArray(); 

从那里开始:

 <# foreach (var field in fieldsNeedingProperties) { #> <# string propertyName = GetPropertyName(field.Name); #> public <#= field.FieldType.FullName #> <#= propertyName #> { get { return <#= field.Name #>; } set { <#= field.Name #> = value; OnPropertyChanged("<#= propertyName #>"); } } <# } #> <#+ private string GetPropertyName(string fieldName) { return fieldName.Substring(2, fieldName.Length - 2); } #> 

等等。