我有一个类CustomControl,它继承自System.Windows.Forms.Control。我还将创建一个名为GraphicsData的新类,该类将包含有关我的CustomControl的所有图形信息(我需要它,因为它更容易序列化数据以将其保存在DB、json等中(
CustomControl对象将在初始化时(在构造函数中(获得GraphicsData,我希望它获得GraphicsDatas中有值的所有属性(有时我不想从GraphicsData初始化所有属性,我希望它们在System.Windows.Forms.Control类中保持默认值(。
问题是,大多数属性都是不可为null的,我无法检查它们是否为null,因此我无法执行简单的操作:
customControl.BackColor = graphicsData.BackColor.HasValue ? graphicsData.BackColor.Value : BackColor;
如果我创建自己的Nullable类,我当然可以解决这个问题,但这变得非常丑陋,很难理解代码。此外,在需要时很难添加新属性。
现在,我所做的,我认为这是一种更干净的方式,如下所示:
GraphicsData类:
public class GraphicsData : INotifyPropertyChanged
{
private readonly List<string> _initializedProperties = new List<string>();
public List<string> InitializedProperties { get { return _initializedProperties; } }
public event PropertyChangedEventHandler PropertyChanged;
private Size _size;
private Point _location;
private AnchorStyles _anchor;
private Color _backColor;
private Image _backgroundImage;
private Cursor _cursor;
private Font _font;
private Color _foreColor;
private bool _enabled;
private bool _visible;
public Size Size
{
get { return _size; }
set
{
_size = value;
OnPropertyChanged("Size");
}
}
public Point Location
{
get { return _location; }
set
{
_location = value;
OnPropertyChanged("Location");
}
}
public AnchorStyles Anchor
{
get { return _anchor; }
set
{
_anchor = value;
OnPropertyChanged("Anchor");
}
}
public Color BackColor
{
get { return _backColor; }
set
{
_backColor = value;
OnPropertyChanged("BackColor");
}
}
public Image BackgroundImage
{
get { return _backgroundImage; }
set
{
_backgroundImage = value;
OnPropertyChanged("BackgroundImage");
}
}
public Cursor Cursor
{
get { return _cursor; }
set
{
_cursor = value;
OnPropertyChanged("Cursor");
}
}
public Font Font
{
get { return _font; }
set
{
_font = value;
OnPropertyChanged("Font");
}
}
public Color ForeColor
{
get { return _foreColor; }
set
{
_foreColor = value;
OnPropertyChanged("ForeColor");
}
}
public bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
OnPropertyChanged("Enabled");
}
}
public bool Visible
{
get { return _visible; }
set
{
_visible = value;
OnPropertyChanged("Visible");
}
}
protected void OnPropertyChanged(string propertyName)
{
if (!_initializedProperties.Contains(propertyName))
_initializedProperties.Add(propertyName);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
在我的自定义控制中,我有一个方法:
public void LoadGraphics()
{
var initializedProperties = graphics.InitializedProperties;
foreach (string propertyName in initializedProperties)
{
var value = graphics.GetType()
.GetProperty(propertyName)
.GetValue(graphics, null);
_customControl.GetType()
.GetProperty(propertyName)
.SetValue(_customControl, value, null);
}
}
基本上,我创建了一个名为InitializedProperties的List,并在属性"集合"中将该属性添加到列表中。之后,在我的CustomControl中使用反射,我可以加载所有初始化的属性。
我实现了INotifyPropertyChanged,因为我还想在每次GraphicsData中的属性更改时更改customControl属性。
这是做我想做的事的正确方式吗?我不认为反射代码是可读的,我关心的是性能。
使用可为null的值是实现这一点的一种简单得多的方法。
C#已经有了一个内置的Nullable
类,但它也提供了一种简单的方法,可以使值为null,而不会像Nullable
类引入的那样冗长:?
。
通过将?
运算符附加到值类型中,可以使所有值为null:
private Size? _size;
private Point? _location;
private AnchorStyles? _anchor;
private Color? _backColor;
private Image _backgroundImage;
private Cursor _cursor;
private Font _font;
private Color? _foreColor;
private bool? _enabled;
private bool? _visible;
LoadGraphics
方法可以很容易地检查GraphicsData属性是否有非null值,如果有,则设置相应的控件属性。
public void LoadGraphics(GraphicsData gfx)
{
// It may be permissible to utilize a null value for BackgroundImage!
// In this case, utilizing a separate field (IsBackgroundImageSet) may be a necessary
if (gfx.BackgroundImage != null) { _customControl.BackgroundImage = gfx.BackgroundImage; }
if (gfx.Size != null) { _customControl.Size = gfx.Size.Value; }
if (gfx.Location != null) { _customControl.Location = gfx.Location.Value }
if (gfx.Anchor != null) { _customControl.Anchor = gfx.Anchor.Value; }
if (gfx.BackColor != null) { _customControl.BackColor = gfx.BackColor .Value; }
if (gfx.Cursor != null) { _customControl.Cursor = gfx.Cursor; }
if (gfx.Font != null) { _customControl.Font = gfx.Font; }
if (gfx.Color != null) { _customControl.Color = gfx.Color.Value; }
if (gfx.Enabled != null) { _customControl.Enabled = gfx.Enabled.Value; }
if (gfx.Visible != null) { _customControl.Visible = gfx.Visible.Value; }
}