假设有一个通用的用户页面控件提供操作,并在大多数应用程序页面上重用。常见的操作如:保存,取消,重置,发送等。目前它有大约10个。
特定的操作状态通常但不一定取决于页面上显示的实体及其状态。如果要创建新实体,则可以显示并启用保存和取消。但是当我们编辑现有的保存时,可以主动显示取消和重置。
由于这个带动作的常见控件是状态解耦并且不知道页面的上下文(或实体类型及其状态)我决定给它注入挂钩,以便页面可以提供操作按钮getter,这是常见的控制然后会使用。
我没有定义事件和委托,而是决定采用简化类型的大致相同的方案。我刚刚使用了Func<bool>
属性,但可以很容易地将它们转换为事件/委托。这仍然是他们现在定义的方式(例如发送动作):
private Func<bool> DefaultState = () => false;
private Func<bool> isSendVisible;
public Func<bool> IsSendVisible
{
private get { return isSendVisible ?? DefaultState; }
set { isSendVisible = value; }
}
private Func<bool> isSendEnabled;
public Func<bool> IsSendEnabled
{
private get { return isSendEnabled ?? DefaultState; }
set { isSendEnabled = value; }
}
问题是我在界面中定义了这几个属性:
public interface ISendActionProvider
{
Func<bool> IsSendVisible { set; }
Func<bool> IsSendEnabled { set; }
}
我的公共控件实现了这个接口(以及其他动作的接口),但是其他控件(甚至页面本身)可以提供相同的接口,因此可以在多个位置显示相同的按钮,并重用相同的动作状态机制。页面只需要在初始化期间将其getter绑定到提供者,因此操作提供者可以适当地设置操作状态。
问题在于,每次我必须为它添加相同的接口和实现,这导致相当多的半复制代码。
如果我可以拥有一个单独的接口并为每个动作实现它,那将是很好的,所以它可以由一个类(动作提供者类 - 在我的情况下提供这些动作的公共控件)实现多次。这可以在C#中工作的唯一方法是通过一个通用接口,然后根据需要提供尽可能多的实现。但我没有区分泛型类型来提供多种通用接口实现。
public interface IActionProvider // multiple inplementations?
{
Func<bool> IsActionVisible { set; }
Func<bool> IsActionEnabled { set; }
}
实现的工作方式(如上所示)是每个操作都定义了其默认行为,但特定页面可以通过提供自己的getter来为特定操作提供其状态来覆盖它。
我想要的是某种通用属性提供程序,可以在初始化绑定期间调用它们:
(provider as IActionProvider<TSend>).IsActionVisible<TSend> = this.IsSendVisible;
但如上所述,我没有这种差异化的通用类型。
答案 0 :(得分:0)
注意:我自己回答了这个问题,并提出了一个我不太喜欢但可以满足要求的解决方案。我还在等待更好的建议。
我可能只有一个具有不同定义的接口,而不是几个接口及其实现:
public interface IActionProvider
{
void SetVisibleGetter(ActionType type, Func<bool> getter);
void SetEnabledGetter(ActionType type, Func<bool> getter);
}
然后,实现可以使用某种字典来处理各个动作类型:
private IDictionary<ActionType, Func<bool>> isActionVisible = new Dictionary<ActionType, Func<bool>> {
{ ActionType.Cacel, AlwaysFalse }
{ ActionType.Send, AlwaysFalse },
...
};
public void SetVisibleGetter(ActionType type, Func<bool> getter)
{
this.isActionVisible[type] = getter ?? this.isActionVisible[type];
}
...
然后在动作提供者控件中使用它,需要像这样设置动作的状态:
linkSend.Visible = this.isActionVisible[ActionType.Send]();
答案 1 :(得分:0)
您可以提供默认实现并使用继承来覆盖默认实现。
E.G。
public class SubmitActionProvider:ActionProvider
{
public override Func<bool> IsActionVisible
{
get
{
Console.WriteLine("submit");
return null;
}
}
}
public class CancelActionProvider : ActionProvider
{
public override Func<bool> IsActionVisible
{
get
{
Console.WriteLine("cancel");
return null;
}
}
}
public class ActionProvider
{
public virtual Func<bool> IsActionVisible { get { Console.WriteLine("Default implementation"); return null; } }
public virtual Func<bool> IsActionEnabled { set { } }
}