C# 在C语言中优雅地处理重复的属性代码#
语言捷径C# 在C语言中优雅地处理重复的属性代码#,c#,visual-studio,c#-4.0,properties,C#,Visual Studio,C# 4.0,Properties,语言捷径 public string Code { get; set; } 在C#中定义琐碎属性时节省了一点键入时间 然而,我发现自己编写的是高度重复的,而不是仍然遵循清晰模式的琐碎属性代码 public string Code { get { return code; } set { if (code != value) { code = value; NotifyPr
public string Code
{
get;
set;
}
在C#中定义琐碎属性时节省了一点键入时间
然而,我发现自己编写的是高度重复的,而不是仍然遵循清晰模式的琐碎属性代码
public string Code
{
get { return code; }
set
{
if (code != value)
{
code = value;
NotifyPropertyChanged("Code");
}
}
}
我当然可以定义一个VisualStudio代码段来减少键入。然而,如果我需要向我的模式中添加一些东西,我必须返回并更改相当多的现有代码
有没有更优雅的方法?一个片段是最好的方法吗
更新:
作为目前的一个快速改进,我编辑了(备份后)
C:\Program Files\Microsoft Visual Studio 10.0\VC\Snippets\1033\Refactoring\EncapseField.snippet
(路径为VS 2010)
以反映我目前的模式。现在,内置重构工具使用my template从字段创建属性。缺点:Visual Studio的全局更改,无法追溯更改现有属性代码。这是一种非常常见的模式。代码片段还可以,但是,如果MS为自动属性更改通知创建了一些语法糖,那岂不是太好了 像
public string Code { get; setwithnotify; }
那真是太好了。我自己还没有做过,但是我已经看到一个依赖注入框架被用于这个特定的任务 谷歌和谷歌 啊哈 似乎可以使用将
INotifyPropertyChanged
注入自动属性。看看这篇很棒的博文:
这让我想起了最近的一次HanselMinutes,Scott正在和一个家伙谈论面向方面编程(AOP),这种类型的注入非常常见。我讨厌编写这种代码
过去,为了解决这个问题,我实现了一个代码生成器,用属性定义生成一个
部分
类。最初灵感来源于乔恩·斯基特的作品
要回答有关重复代码的一般问题,而不仅仅是属性更改通知案例,请执行以下操作: 当然。对于宏来说,这是一个完美的例子 哦,等等。C#没有宏。当然,宏是邪恶的,并不是任何编程问题的最佳解决方案 除非在构建中插入预处理器。这称为(AOP) Scott Hanselman最近就这个话题采访了LinFu的创始人Philip Laureano。() 根据您的需要,有许多AOP工具
- (团结的一部分)
- 后夏普
(以前的NotifyPropertyWeaver)是一个编译后IL-weaver,它将自动为您插入属性更改代码。这是我现在首选的INotifyPropertyChanged解决方案。感谢大家的回复。我对有用的答案投了赞成票。然而,经过相当多的研究,我开始相信最好的答案(至少对我和我开发软件的方式来说)是在VisualStudio中建模类,并使用T4代码生成实现属性代码的部分类
请参见查看NotifyPropertyWeaver:DI看起来非常有前途。虽然问题中没有说明,但我目前正在与Silverlight合作。不知道Unity2.0forSilverlight是否也支持这种模式(不知道与标准版相比,他们必须省略什么)。我自己过去也曾从UML模型生成代码。当项目“足够大”以保证基于模型的方法和代码生成器的创建时,这是一种很好的方法。随着建模工具越来越强大/集成,“足够大”的门槛不断降低。@Eric:就我个人而言,我会避免UML及其所有的智能开销。我认为您的目标很简单:具有属性的类在更改时通知。一个简单的解决方案可能是一个PowerShell脚本,它允许您编写:
class C{property string code;}
,并生成一个分部类。我以前也这样做过,当时我还想要一个流畅的类接口。这是一种使用扩展方法的有趣方法,尽管我没有完全遵循实现。“新{Title},Title”部分是做什么的?为什么不引用“值”呢?呵呵,它实际上是Jon Skeet在很久以前提出的,是在运行时获取属性名称的一种方法<代码>值没有被引用实际上是一个bug,因为它是从其他地方提出来的。我会修正它并扩展解决方案。谢谢你的澄清。当然是一个有趣的方法!是的,这将处理这个特定的模式,但是仍然没有解决重复某些任意模式的一般问题-理想情况下,可以插入对给定属性的修改。这不是答案,而是讨论,因此最好将其作为对原始问题的注释。除此之外,我认为将框架中的概念过多地嵌入C#语法不是一个好主意。一旦InotifyPropertyChange过时(只看依赖属性),我们就剩下一个遗留概念了。没有帮助(如果问题是在c++中,这甚至不是一个好的建议),这正是Jay Bazuzi所建议的,不是吗?NotifyPropertyWeaver已被弃用,取而代之的是NotifyPropertyWeaver。看见
public static class ObjectExtensions {
public static string GetPropertyNameAndValue<T>(this T obj, out object value) {
System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
if(objGetTypeGetProperties.Length == 1) {
value = objGetTypeGetProperties[0].GetValue(obj, null);
return objGetTypeGetProperties[0].Name;
} else
throw new ArgumentException("object must contain one property");
}
}
class Whatever {
protected void ChangeProperty<T>(object property, T newValue, Action change) {
object value;
var name = property.GetPropertyNameAndValue(out value);
if(value == null && newValue != null || value != null && !value.Equals(newValue)) {
change();
OnPropertyChanged(name);
}
}
private string m_Title;
public string Title {
get { return m_Title; }
set {ChangeProperty(
new { Title }, //This is used to dynamically retrieve the property name and value
value, // new value
() => m_Title = value); //lambda to change the value
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propfullinotify</Title>
<Shortcut>propfullinotify</Shortcut>
<Description>Code snippet for property and backing field with INotifyPropertyChanged</Description>
<Author>Microsoft Corporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>The variable backing this property</ToolTip>
<Default>myVar</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ $field$;
public $type$ $property$
{
get { return $field$;}
set {
if ($field$ != value)
{
$field$ = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("$property$"));
}
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>