我在MVVM
项目中重复此属性的次数太多了。创建泛型类或工厂来替换这些代码行的正确方法是什么?
ObservableCollection<Result> _resultCollection;
public ObservableCollection<Result> ResultCollection
{
get
{
if (_resultCollection == null)
_resultCollection = new ObservableCollection<Result>();
return _resultCollection;
}
set
{
_resultCollection = value;
}
}
答案 0 :(得分:3)
我知道这并不能完全回答你的问题,不过我个人更喜欢在Visual Studio中使用录制的宏来为我编写所有内容。
我更喜欢将它用于泛型类,因为它将所有相关代码保存在一个地方,并且很容易理解发生了什么。通常我将所有私有字段放在我的类的顶部,并隐藏我保持折叠的#region
标记中的所有公共属性,因此我不需要滚动它们。
在VS中创建宏非常容易:只需转到工具&gt;宏&gt;记录临时宏,然后仅使用键盘执行所需的更改。一旦宏正常工作,只需将其保存为永久宏。如果你做得对,你可以用任何变量重新运行宏,它将以相同的方式构建它。
创建宏时要记住的一些有用的键盘快捷键是:
您可能还需要对VB宏代码进行一些小修改,例如.Replace()
将小写字母转换为大写字母。
这是我用来构建MVVM的所有公共属性的示例宏。它使用PRISM库,因此它使用语法RaisePropertyChanged(() => this.SomeProperty);
Sub PRISM_BuildPropertyChanged_CursorAtDefaultAfterCtrlRE()
DTE.ActiveDocument.Selection.LineDown(False, 2)
DTE.ActiveDocument.Selection.WordLeft(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.LineDown(False, 3)
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "RaisePropertyChanged(() => this."
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = ");"
DTE.ActiveDocument.Selection.LineUp()
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
DTE.ActiveDocument.Selection.CharRight(False, 4)
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.CharRight()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "if (value != "
DTE.ActiveDocument.Selection.WordRight(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.DeleteLeft()
DTE.ActiveDocument.Selection.Text = ")"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
End Sub
有了它,我可以编写我的私人定义,例如
private ObservableCollection<SomeObject> _someCollection;
点击 Ctrl + R , E 来构建公共属性定义
private ObservableCollection<SomeObject> _someCollection;
public ObservableCollection<SomeObject> SomeCollection
{
get { return _someCollection; }
set { _someCollection = value; }
}
然后运行我的宏来构建属性更改通知
public ObservableCollection<SomeObject> SomeCollection
{
get { return _someCollection; }
set
{
if (value != _someCollection)
{
_someCollection = value;
RaisePropertyChanged(() => this.SomeCollection);
}
}
}
(默认情况下, Ctrl + R , E 将光标放在私有字段定义的末尾,这是运行此代码时光标所在的位置宏)
我还有另一个旧宏,它添加了检查值是否为null的代码,如果是,则将其设置为对象的新实例,但是我从未使用过很多,因为我更喜欢设置我的默认定义构造函数而不是属性定义。
如果你想要它,它看起来像这样(注意宏名称 - 你需要在运行这个宏之前突出显示公共属性名称):
Sub CreatePublicGet_NoNull_HightlightPropertyNameFirst()
DTE.ActiveDocument.Selection.CharLeft(False, 2)
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, True)
DTE.ActiveDocument.Selection.WordRight(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.LineDown(False, 2)
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
DTE.ActiveDocument.Selection.CharRight(False, 4)
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.CharRight()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.LineUp(False, 2)
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = "();"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.WordLeft(True)
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.WordLeft(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.LineUp(False, 2)
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "if ("
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = " == null)"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
DTE.ActiveDocument.Selection.LineUp()
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = " = new "
DTE.ActiveDocument.Selection.Collapse()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.LineDown(False, 4)
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.LineUp(True)
DTE.ActiveDocument.Selection.Delete()
End Sub
结果代码如下:
public ObservableCollection<SomeObject> SomeCollection
{
get
{
if (_someCollection == null)
{
_someCollection = new ObservableCollection<SomeObject>();
}
return _someCollection;
}
}
答案 1 :(得分:0)
如果没有某种形式的代码生成,AFAIK是不可能的。查看T4模板,回答here
答案 2 :(得分:0)
public abstract class XBase<T>
{
ObservableCollection<T> _resultCollection;
public ObservableCollection<T> ResultCollection
{
get
{
if (_resultCollection == null)
_resultCollection = new ObservableCollection<T>();
return _resultCollection;
}
set
{
_resultCollection = value;
}
}
}
答案 3 :(得分:0)
是的......能够绑定到一个字段会很棒,不会...... ;-)这会带我去第一个解决方案:
(1)创建一个允许绑定字段的转换器。
public class FieldBindingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var par = parameter as string;
var field = value.GetType().GetField(par);
return field.GetValue(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后(2)直接从XAML绑定字段:
<ItemsControl ItemsSource="{Binding ., Converter={StaticResource Field}, ConverterParameter=Coll2}" Grid.Row="1">
我有点不喜欢这是诚实的,因为它并没有真正清楚......所以作为第二个解决方案,你可以直接从构造函数中实例化该属性:
public Foo()
{
ResultCollection = new ObservableCollection<Result>();
}
[...]
public ObservableCollection<Result> ResultCollection { get; private set; }
虽然这确实增加了几个字节的内存占用(它将延迟实例化的语义更改为直接实例化),但我不会太在意它。