Mik*_*fer 15 c# delegates software-design
考虑以下控件(为简洁而剪切):
public partial class ConfigurationManagerControl : UserControl
{
public Func<string, bool> CanEdit { get; set;}
public Func<string, bool> CanDelete { get; set; }
public Dictionary<string, string> Settings
{
get { return InnerSettings; }
set
{
InnerSettings = value;
BindData();
}
}
private Dictionary<string, string> InnerSettings;
private void OnListIndexChanged(object sender, EventArgs e)
{
this.EditButton.Enabled = false;
this.DeleteButton.Enabled = false;
var indices = this.List.SelectedIndices;
if (indices.Count != 1)
{
return;
}
var index = indices[0];
var item = this.List.Items[index];
if (this.CanEdit != null)
{
this.EditButton.Enabled = this.CanEdit(item.Text);
}
if (this.CanDelete != null)
{
this.DeleteButton.Enabled = this.CanDelete(item.Text);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个控件还有更多内容,但足以说它允许用户添加,编辑和删除Dictionary <string,string>中的条目.为了确定它是否应允许用户编辑或删除条目,它使用委托方法属性 CanDelete和CanEdit,它们由托管它的表单或控件提供:
public class SetupWizard : Form
{
public SetupWizard()
{
InitializeComponent();
this.SettingManager.CanEdit = CanEditSetting;
this.SettingManager.CanDelete = CanDeleteSetting;
}
private static bool CanEditSetting(string item)
{
var lockedSettings = new[] { "LicenseHash", "ProductHash" };
return !lockedSettings.Contains(item.ToLower());
}
private static bool CanDeleteSetting(string item)
{
var lockedSettings = new[] {
"LicenseHash",
"ProductHash",
"UserName",
"CompanyName"
};
return !lockedSettings.Contains(item.ToLower());
}
}
Run Code Online (Sandbox Code Playgroud)
我发现这种设计既令人满意又令人担忧.一方面,似乎使用最简单的解决方案来解决问题(它确实很好地区分了问题).在另一方面,我有我使用不当的代表,应使用一个事件,而是这唠叨的关注(尽管我并不需要多个监听器,只需要来电告诉我,如果项目可编辑).
然后,另一方面,有一个完全不同的设计,我甚至没有考虑过可能以一种非常优越的方式解决问题.
所以.这种设计在技术上是否正确,可维护且灵活?或者我应该做得更好?
Dan*_*rth 11
我建议使用这两种方法的接口.那更清洁了:
interface ICantThinkOfAGoodName
{
bool CanEdit(string item);
bool CanDelete(string item);
}
Run Code Online (Sandbox Code Playgroud)
您可以创建类似于许多MVVM框架中使用的RelayCommand的东西:
public class RelayObject : ICantThinkOfAGoodName
{
public RelayObject() : this(null, null) {}
public RelayObject(Func<string, bool> canEdit, Func<string, bool> canDelete)
{
if(canEdit == null) canEdit = s => true;
if(canDelete == null) canDelete = s => true;
_canEdit = canEdit;
_canDelete = canDelete;
}
public bool CanEdit(string item)
{
return _canEdit(item);
}
public bool CanDelete(string item)
{
return _canDelete(item);
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
public SetupWizard()
{
InitializeComponent();
this.SettingManager.PropertyName = new RelayObject(CanEditSetting,
CanDeleteSetting);
// or (all can be deleted)
this.SettingManager.PropertyName = new RelayObject(CanEditSetting, null);
// or (all can be edited)
this.SettingManager.PropertyName = new RelayObject(null, CanDeleteSetting);
// or (all can be edited and deleted)
this.SettingManager.PropertyName = new RelayObject();
}
Run Code Online (Sandbox Code Playgroud)
BTW:我在这里使用Property注入,因为它是一个控件.通常,我会ICantThinkOfAGoodName在构造函数中传递依赖项ConfigurationManagerControl.