gpt4 book ai didi

c# - 类设计悖论

转载 作者:行者123 更新时间:2023-11-30 15:52:56 25 4
gpt4 key购买 nike

我需要一个类来标识要执行的网络连接类型。

网络加入可以是 Domain 加入 Workgroup 加入。

在加入Workgroup 的情况下,我只需要知道要加入的工作组的Name

Domain 加入的情况下,我需要知道要加入的域的 Name 以及 Username要使用的密码(让我们忽略这里所有关于安全的顾虑,这是一个场景)。

然后我想为它创建一个类似于此的 WPF UI:

http://documents.weber.edu/ctctools/sccm/images/osdnotes/9.png

如果用户选择 Workgroup 加入,GUI 的凭据部分将被禁用,而当他们选择 Domain 加入时,GUI 的凭据部分将被禁用(关于名称也是如此要加入的实际工作组/域)。

而且我希望能够序列化/反序列化这些数据(再次忽略安全问题,这是一个场景)。

在我看来,我有两个选择:

选项 1

创建类似于以下的解决方案:

enum JoinType
{
Domain,
Workgroup
}

class NetworkJoin
{
JoinType JoinType {get; set;}
string Name {get;set;}
string Username {get;set;}
SecureString Password {get;set;}

void Join()
{
// Join code for domain + workgroup
}
}

这将使我能够轻松地执行 TextBoxUsername.IsEnabled = ViewModel.NetworkJoin.JoinType == JoinType.Domain

但是,因为类实例是序列化/反序列化的,所以它允许此类的实例具有 JoinType = JoinType.Workgroup 以及具有 Username/Password 并且这是一个假设(尽管是合乎逻辑的)网络加入是基于对 JoinType 的检查(而不是说,if (Username == null) {//工作组加入 })

这让我想到了选项 2

选项 2

类似于:

interface INetworkJoin
{
string Name {get;set;}
void Join();
}

class DomainJoin : INetworkJoin
{
string Name {get;set;}
string Username {get;set;}
SecureString {get;set;}
void Join()
{
// Domain join code
}
}

class WorkgroupJoin : INetworkJoin
{
string Name {get;set;}
void Join()
{
// Workgroup join code
}
}

现在您不可能创建具有错误属性的对象或任何关于将执行哪种类型的连接的假设,因为我们传递的参数不明确。

事实上,通常这会是一个更好的解决方案。除了将它绑定(bind)到 UI。

我的 ViewModel 基本上会有一个 INetworkJoin NetworkJoin,这意味着我的 View 只会看到一个 INetworkJoin。它需要知道它的具体类型以确定是否显示/不显示凭据对象,它需要将用户名文本框绑定(bind)到用户名属性(INetworkJoin 没有...) , 密码等也一样

总结

如果感觉这两种解决方案都不合适。第一个提供不明确的连接,第二个需要找出接口(interface)的具体类型,以及访问仅在具体类型中可用的属性。

我想一定有比这两个更好的解决方案,但这真的是我能想到的。

如有任何帮助,我们将不胜感激。

最佳答案

您应该有单独的域模型和 View 模型。 View 模型通常还实现 INotifyPropertyChanged 并具有其他属性,例如启用/禁用按钮等。

领域模型:

abstract class NetworkJoin
{
public string Name { get; set; }
}

class WorkgroupJoin : NetworkJoin
{
}

class DomainJoin : NetworkJoin
{
public string Username { get; set; }
public SecureString Password { get; set; }
}

查看模型(为了简单起见,我没有显示 INotifyPropertyChanged 实现。对 NameUsernamePassword< 的更改 必须触发 OnPropertyChanged(nameof(IsOkButtonEnabled)):

class NetworkJoinViewModel
{
private const int MinPasswordLength = 8;

public JoinType JoinType { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public SecureString Password { get; set; }

public bool IsOkButtonEnabled
{
get {
switch (JoinType) {
case JoinType.Domain:
return
!String.IsNullOrEmpty(Name) &&
!String.IsNullOrEmpty(Username) &&
Password != null && Password.Length >= MinPasswordLength;
case JoinType.Workgroup:
return !String.IsNullOrEmpty(Name);
default:
return false;
}
}
}

public bool IsLoginEnabled => JoinType == JoinType.Domain; // For password an username textboxes.

public void Join()
{
switch (JoinType) { /* ... */ }
}

public NetworkJoin ToDomainModel() {
switch (JoinType) {
case JoinType.Domain:
return new DomainJoin {
Name = Name,
Username = Username,
Password = Password
};
case JoinType.Workgroup:
return new WorkgroupJoin {
Name = Name
};
default:
return null;
}
}
}

最后是 View 模型工厂(因为我不想向域模型添加 ToViewModel 方法。域模型不应该知道 View 模型的详细信息):

static class NetworkJoinViewModelFactory
{
public static NetworkJoinViewModel Create(NetworkJoin networkJoin)
{
switch (networkJoin) {
case WorkgroupJoin workgroupJoin:
return new NetworkJoinViewModel {
JoinType = JoinType.Workgroup,
Name = workgroupJoin.Name
};
case DomainJoin domainJoin:
return new NetworkJoinViewModel {
JoinType = JoinType.Domain,
Name = domainJoin.Name,
Username = domainJoin.Username,
Password = domainJoin.Password
};
default:
return null;
}
}
}

关于c# - 类设计悖论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53523359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com