Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 全局可读配置,仅从特定类更新_C#_Dependency Injection_Singleton_Observer Pattern_Mediator - Fatal编程技术网

C# 全局可读配置,仅从特定类更新

C# 全局可读配置,仅从特定类更新,c#,dependency-injection,singleton,observer-pattern,mediator,C#,Dependency Injection,Singleton,Observer Pattern,Mediator,我的C#7应用程序可以归结为一个具有三种可能状态的巨型状态机。我的很多对象需要了解当前状态,因为它们在不同状态下的行为不同。与中一样,我可以在不同的状态下翻转文本框的可见性,也可以根据状态更改操作的内容。我相信我的问题针对的是C#中的特定设计模式,而不是我选择的框架,但我使用的是WPF。我将根据要求添加此标签 我希望摆脱状态可枚举(单例模式)的全局可访问性。因此,我将我的顶级容器,MainViewModel放入一个依赖项注入容器中,并且只将我的状态可枚举注入那些需要知道状态的对象中。我找到了一个

我的C#7应用程序可以归结为一个具有三种可能状态的巨型状态机。我的很多对象需要了解当前状态,因为它们在不同状态下的行为不同。与中一样,我可以在不同的状态下翻转文本框的可见性,也可以根据状态更改操作的内容。我相信我的问题针对的是C#中的特定设计模式,而不是我选择的框架,但我使用的是WPF。我将根据要求添加此标签

我希望摆脱状态可枚举(单例模式)的全局可访问性。因此,我将我的顶级容器,
MainViewModel
放入一个依赖项注入容器中,并且只将我的状态可枚举注入那些需要知道状态的对象中。我找到了一个类似于以下内容的解决方案:

enum属性
{
传感输入,
不活跃的
输出,
}
阶级地位
{
公共MachineState状态=MachineState.SensingInputs;
公共请求更新(不动产状态)
{
bool validTimeToChange=此处未定义函数(状态);
如果(validTimeChange)this.state=状态;
}
}
类MainViewModel
{
地位;
公共主视图模型()
{
状态=新状态();
MyClass1 object1=新的MyClass1(状态);
MyClass2 object2=新的MyClass2();
MyClass3 object3=新的MyClass3(状态);
}
}
问题是,任何拥有当前状态引用的人都可以访问任何公共方式来改变当前状态(
RequestToUpdate(Status)
)。我只希望我的类的一个子集能够修改
状态
。起初,在我看来,这似乎是观察者模式的理想情况:

类状态
{
公共MachineState状态=MachineState.SensingInputs;
公共HandlerRequestToUpdate(对象发送器、MachineStateEventTarget e)
{
bool validTimeToChange=此处未定义函数(如状态);
如果(ValidTimeChange)this.state=e.state;
}
}
类MainViewModel
{
地位;
公共主视图模型()
{
状态=新状态();
MyClass1 object1=新的MyClass1(状态);
MyClass2 object2=新的MyClass2();
MyClass3 object3=新的MyClass3(状态);
object3.RequestToUpdate+=status.handleRequestToUpdate;
}
}
但这个解决方案看起来很丑陋。我必须在我要修改的每个类中声明
事件RequestToUpdate
和一个方法来像
OnRequestToUpdate()
一样引发它。此外,这些类中的每一个都需要了解
machinestateventargs
这种重复的样板文件数量让我感到困扰,但我不能完全定位它。也许它打破了单一责任原则/封装

所以观察者模式让我失望了。我的下一个想法是尝试使用中介模式将所有这些代码封装到一个类中,只将
executeRequestToUpdate(Status)
暴露给注入依赖项的类:

类状态//状态与上面的观察者模式相同
{
公共MachineState状态=MachineState.SensingInputs;
公共HandlerRequestToUpdate(对象发送器、MachineStateEventTarget e)
{
bool validTimeToChange=此处未定义函数(如状态);
如果(ValidTimeChange)this.state=e.state;
}
}
类状态中介
{
公共状态调解员(状态)
{
RequestToUpdate+=status.handleRequestToUpdate;
}
公共事件事件处理程序RequestToUpdate;
公共执行者请求更新(州)
{
RequestToUpdateEventArgs e=新的RequestToUpdateEventArgs()
RequestToUpdate?调用(this,e);
}
}
类MainViewModel
{
地位;
状态调解员;
公共主视图模型()
{
状态=新状态();
调解员=新状态调解员(状态);
MyClass1 object1=新的MyClass1(状态);
MyClass2 object2=新的MyClass2();
MyClass3 object3=新的MyClass3(状态、中介);
}
}

这是我自己想出的最不丑陋的解决方案。我不知道在Google中键入正确的术语来查找其他示例,但我怀疑我的问题是否独特。社区,有没有更好的方法来解决我的问题?我认为使用不可变变量的线程安全解决方案会更好,但我对如何实现这一点信心不足

我只需要依靠封装和声明两个接口来公开
状态
对象的不同职责

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);
    }
}

在不太可能的情况下,您希望“读”和“写”是完全独立的责任,您可以删除两个接口之间的继承。

顺便说一下,您的两种模式实现都是错误的。哦,嗯,如果有人想重做我的代码,以帮助未来的访问者看到正确的实现,我会允许他们。我想我不知道正确的实现方法。