全局可读配置,仅从特定 类 更新
Globally readable configuration, updated from only specific classes
我的 C#7 应用程序归结为一个具有三种可能状态的巨型状态机。我的很多对象都需要了解当前状态,因为它们在不同状态下的行为不同。例如,我可能会在不同状态下翻转文本框的可见性,或者我可能会根据状态更改操作的内容。我相信我的问题针对的是 C# 中的特定设计模式,而不是我选择的框架,但我使用的是 WPF。我会根据要求添加此标签。
我希望远离状态可枚举的全局可访问性(单例模式)。所以我将我的顶级容器 MainViewModel
变成了 Dependency Injection 容器,并且只将我的状态可枚举注入到那些需要知道状态的对象中。我找到了类似于以下内容的解决方案:
enum MachineState
{
SensingInputs,
Inactive,
Outputting,
}
class Status
{
public MachineState state = MachineState.SensingInputs;
public RequestToUpdate(MachineState state)
{
bool validTimeToChange = FunctionNotDefinedHere(state);
if (validTimeToChange) this.state = state;
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status);
}
}
问题是,任何引用它以读取当前状态的人也可以使用任何 public 方法来改变当前状态 (RequestToUpdate(Status)
)。我只希望我的 classes 的一个子集能够修改 Status
。起初,在我看来,这似乎是 观察者模式:
的理想情况
class Status
{
public MachineState state = MachineState.SensingInputs;
public handleRequestToUpdate(Object sender, MachineStateEventArgs e)
{
bool validTimeToChange = FunctionNotDefinedHere(e.state);
if (validTimeToChange) this.state = e.state;
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status);
object3.RequestToUpdate += status.handleRequestToUpdate;
}
}
但是这个解决方案看起来很难看。我必须在每个 class 中声明 event RequestToUpdate
和一个像 OnRequestToUpdate()
一样引发它的方法我想修改 Status
。此外,这些 class 中的每一个都需要 MachineStateEventArgs
的知识。这些重复的样板文件让我很困扰,但我无法完全理解。也许它打破了单一职责原则/封装。
所以观察者模式让我失望了。我的下一个想法是尝试 中介模式 将所有这些代码封装到一个 class 中,仅将 executeRequestToUpdate(Status)
暴露给它所在的那些 classes是否注入依赖项:
class Status // Status is same as Observer pattern above
{
public MachineState state = MachineState.SensingInputs;
public handleRequestToUpdate(Object sender, MachineStateEventArgs e)
{
bool validTimeToChange = FunctionNotDefinedHere(e.state);
if (validTimeToChange) this.state = e.state;
}
}
class StatusMediator
{
public StatusMediator(Status status)
{
RequestToUpdate += status.handleRequestToUpdate;
}
public event EventHandler<RequestToUpdateEventArgs> RequestToUpdate;
public executeRequestToUpdate(MachineState state)
{
RequestToUpdateEventArgs e = new RequestToUpdateEventArgs()
RequestToUpdate?.Invoke(this, e);
}
}
class MainViewModel
{
Status status;
StatusMediator mediator;
public MainViewModel()
{
status = new Status();
mediator = new StatusMediator(status);
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status, mediator);
}
}
这是我自己想出的最不丑陋的解决方案。我不知道输入 Google 以查找其他示例的正确术语,但我怀疑我的问题是独一无二的。社区,有没有更好的方法来解决我的问题?我认为使用不可变变量的线程安全解决方案会更好,但我对如何实现它不太有信心。
我就靠封装,声明两个接口来暴露Status
对象的不同职责。
interface IReadOnlyStatus
{
MachineState State { get; }
}
interface IStatus : IReadOnlyStatus
{
void RequestToUpdate(MachineState state);
}
public class Status : IStatus
{
MachineState State { get; private set; }
void RequestToUpdate(MachineState state)
{
bool validTimeToChange = FunctionNotDefinedHere(state);
if (validTimeToChange) this.State = state;
}
}
从那里,您可以根据需要注入一个或另一个:
// Can only read status
class MyClass1
{
MyClass1(IReadOnlyStatus status)
{
}
}
// Can read and update status
class MyClass3
{
MyClass3(IStatus status)
{
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
// The cast is not necessary but added for clarity
MyClass1 object1 = new MyClass1((IReadOnlyStatus)status);
MyClass3 object3 = new MyClass3((IStatus)status);
}
}
在不太可能的情况下,您希望 "reading" 和 "writing" 是完全独立的职责,您可以删除两个接口之间的继承。
我的 C#7 应用程序归结为一个具有三种可能状态的巨型状态机。我的很多对象都需要了解当前状态,因为它们在不同状态下的行为不同。例如,我可能会在不同状态下翻转文本框的可见性,或者我可能会根据状态更改操作的内容。我相信我的问题针对的是 C# 中的特定设计模式,而不是我选择的框架,但我使用的是 WPF。我会根据要求添加此标签。
我希望远离状态可枚举的全局可访问性(单例模式)。所以我将我的顶级容器 MainViewModel
变成了 Dependency Injection 容器,并且只将我的状态可枚举注入到那些需要知道状态的对象中。我找到了类似于以下内容的解决方案:
enum MachineState
{
SensingInputs,
Inactive,
Outputting,
}
class Status
{
public MachineState state = MachineState.SensingInputs;
public RequestToUpdate(MachineState state)
{
bool validTimeToChange = FunctionNotDefinedHere(state);
if (validTimeToChange) this.state = state;
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status);
}
}
问题是,任何引用它以读取当前状态的人也可以使用任何 public 方法来改变当前状态 (RequestToUpdate(Status)
)。我只希望我的 classes 的一个子集能够修改 Status
。起初,在我看来,这似乎是 观察者模式:
class Status
{
public MachineState state = MachineState.SensingInputs;
public handleRequestToUpdate(Object sender, MachineStateEventArgs e)
{
bool validTimeToChange = FunctionNotDefinedHere(e.state);
if (validTimeToChange) this.state = e.state;
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status);
object3.RequestToUpdate += status.handleRequestToUpdate;
}
}
但是这个解决方案看起来很难看。我必须在每个 class 中声明 event RequestToUpdate
和一个像 OnRequestToUpdate()
一样引发它的方法我想修改 Status
。此外,这些 class 中的每一个都需要 MachineStateEventArgs
的知识。这些重复的样板文件让我很困扰,但我无法完全理解。也许它打破了单一职责原则/封装。
所以观察者模式让我失望了。我的下一个想法是尝试 中介模式 将所有这些代码封装到一个 class 中,仅将 executeRequestToUpdate(Status)
暴露给它所在的那些 classes是否注入依赖项:
class Status // Status is same as Observer pattern above
{
public MachineState state = MachineState.SensingInputs;
public handleRequestToUpdate(Object sender, MachineStateEventArgs e)
{
bool validTimeToChange = FunctionNotDefinedHere(e.state);
if (validTimeToChange) this.state = e.state;
}
}
class StatusMediator
{
public StatusMediator(Status status)
{
RequestToUpdate += status.handleRequestToUpdate;
}
public event EventHandler<RequestToUpdateEventArgs> RequestToUpdate;
public executeRequestToUpdate(MachineState state)
{
RequestToUpdateEventArgs e = new RequestToUpdateEventArgs()
RequestToUpdate?.Invoke(this, e);
}
}
class MainViewModel
{
Status status;
StatusMediator mediator;
public MainViewModel()
{
status = new Status();
mediator = new StatusMediator(status);
MyClass1 object1 = new MyClass1(status);
MyClass2 object2 = new MyClass2();
MyClass3 object3 = new MyClass3(status, mediator);
}
}
这是我自己想出的最不丑陋的解决方案。我不知道输入 Google 以查找其他示例的正确术语,但我怀疑我的问题是独一无二的。社区,有没有更好的方法来解决我的问题?我认为使用不可变变量的线程安全解决方案会更好,但我对如何实现它不太有信心。
我就靠封装,声明两个接口来暴露Status
对象的不同职责。
interface IReadOnlyStatus
{
MachineState State { get; }
}
interface IStatus : IReadOnlyStatus
{
void RequestToUpdate(MachineState state);
}
public class Status : IStatus
{
MachineState State { get; private set; }
void RequestToUpdate(MachineState state)
{
bool validTimeToChange = FunctionNotDefinedHere(state);
if (validTimeToChange) this.State = state;
}
}
从那里,您可以根据需要注入一个或另一个:
// Can only read status
class MyClass1
{
MyClass1(IReadOnlyStatus status)
{
}
}
// Can read and update status
class MyClass3
{
MyClass3(IStatus status)
{
}
}
class MainViewModel
{
Status status;
public MainViewModel()
{
status = new Status();
// The cast is not necessary but added for clarity
MyClass1 object1 = new MyClass1((IReadOnlyStatus)status);
MyClass3 object3 = new MyClass3((IStatus)status);
}
}
在不太可能的情况下,您希望 "reading" 和 "writing" 是完全独立的职责,您可以删除两个接口之间的继承。