C#在枚举方面遇到了困难,感觉到了糟糕的代码气味
我很难弄清楚如何做到这一点,基本上我有一个应用程序,它使用枚举来计算出这个人所在的建筑,然后是他们所在的部门 根据此人所在的部门,可以添加不同的组。我想让这个方法只执行一次,直到他们关闭并重新打开应用程序,有点像一个白名单 问题是,当想要使用泛型方法时,枚举似乎是一个巨大的难题 我能想出一个方法来做到这一点,用一个通用的静态字典,但它只是看起来很糟糕,我不知道是否有什么我忽略了,或者有一个更简单的方法来做我想做的事C#在枚举方面遇到了困难,感觉到了糟糕的代码气味,c#,dictionary,generics,enums,C#,Dictionary,Generics,Enums,我很难弄清楚如何做到这一点,基本上我有一个应用程序,它使用枚举来计算出这个人所在的建筑,然后是他们所在的部门 根据此人所在的部门,可以添加不同的组。我想让这个方法只执行一次,直到他们关闭并重新打开应用程序,有点像一个白名单 问题是,当想要使用泛型方法时,枚举似乎是一个巨大的难题 我能想出一个方法来做到这一点,用一个通用的静态字典,但它只是看起来很糟糕,我不知道是否有什么我忽略了,或者有一个更简单的方法来做我想做的事 private async Task CheckWhiteList(PowerS
private async Task CheckWhiteList(PowerShell power, KeyValuePair<string, Enum> history)
{
switch ((Building)Model.BuildingSelectedIndex)
{
case Building.CaneRidge:
history = new KeyValuePair<string, Enum>(Model.UserID, (CaneRidgeSettings.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
case Building.Carothers:
history = new KeyValuePair<string, Enum>(Model.UserID, (CarothersSettings.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
case Building.CSC:
history = new KeyValuePair<string, Enum>(Model.UserID, (CSCSettings.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
case Building.HQ:
history = new KeyValuePair<string, Enum>(Model.UserID, (HQSettings.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
default:
break;
}
专用异步任务检查白名单(PowerShell电源、KeyValuePair历史记录)
{
交换机((建筑)模型BuildingSelectedIndex)
{
case Building.CaneRidge:
历史=新的KeyValuePair(Model.UserID,(CaneRidgeSettings.Departments)Model.DepartmentSelectedIndex);
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
打破
案例建设。其他:
历史记录=新的KeyValuePair(Model.UserID,(CarothersSettings.Departments)Model.DepartmentSelectedIndex);
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
打破
case Building.CSC:
历史=新的KeyValuePair(Model.UserID,(cscscsettings.Departments)Model.DepartmentSelectedIndex);
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
打破
case Building.HQ:
历史=新的KeyValuePair(Model.UserID,(HQSettings.Departments)Model.DepartmentSelectedIndex);
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
打破
违约:
打破
}
请注意,关键是他们的用户ID,我不想将用户可能选择了错误部门或错误建筑的情况列为白名单。这就是为什么它必须同时匹配这两个值。当我看到重复时,我通常会尝试将代码提取到助手函数中 我看到这种模式重复了几次:
case BUILDING:
history = new KeyValuePair<string, Enum>(Model.UserID, (DEPARTMENTSETTINGS.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
既然switch语句只是选择了正确的枚举值,那么我们也可以将其拉到帮助器中,并给它起个好名字:
private async Task CheckWhiteList(PowerShell power)
{
Enum department = GetDepartmentEnumForBuilding((Building)Model.BuildingSelectedIndex);
await InvokeScriptIfNotYetWhiteListedAsync(power, Model.UserID, department);
}
private Enum GetDepartmentEnumForBuilding(Building building)
{
switch (building)
{
case Building.CaneRidge:
return (CaneRidgeSettings.Departments)Model.DepartmentSelectedIndex;
case Building.Carothers:
return (CarothersSettings.Departments)Model.DepartmentSelectedIndex;
case Building.CSC:
return (CSCSettings.Departments)Model.DepartmentSelectedIndex;
case Building.HQ:
return (HQSettings.Departments)Model.DepartmentSelectedIndex;
default:
throw new ArgumentOutOfRangeException(nameof(building));
}
}
private async Task InvokeScriptIfNotYetWhiteListedAsync(PowerShell power, string userID, Enum department)
{
var alreadyWhiteListed = WhiteList.ContainsKey(userID) && WhiteList[userID] == department;
if (!alreadyWhiteListed)
{
WhiteList.Add(userID, department)
await power.InvokeAsync()
}
}
现在似乎没有太多重复的代码,而且每个函数做的工作更少,所以它们可能更容易理解
如果我们不想使用
Enum
,我们还可以进行其他重构,但这可能已经足够好了。当我看到重复时,我通常会尝试将代码拉到助手函数中
我看到这种模式重复了几次:
case BUILDING:
history = new KeyValuePair<string, Enum>(Model.UserID, (DEPARTMENTSETTINGS.Departments)Model.DepartmentSelectedIndex);
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
break;
既然switch语句只是选择了正确的枚举值,那么我们也可以将其拉到帮助器中,并给它起个好名字:
private async Task CheckWhiteList(PowerShell power)
{
Enum department = GetDepartmentEnumForBuilding((Building)Model.BuildingSelectedIndex);
await InvokeScriptIfNotYetWhiteListedAsync(power, Model.UserID, department);
}
private Enum GetDepartmentEnumForBuilding(Building building)
{
switch (building)
{
case Building.CaneRidge:
return (CaneRidgeSettings.Departments)Model.DepartmentSelectedIndex;
case Building.Carothers:
return (CarothersSettings.Departments)Model.DepartmentSelectedIndex;
case Building.CSC:
return (CSCSettings.Departments)Model.DepartmentSelectedIndex;
case Building.HQ:
return (HQSettings.Departments)Model.DepartmentSelectedIndex;
default:
throw new ArgumentOutOfRangeException(nameof(building));
}
}
private async Task InvokeScriptIfNotYetWhiteListedAsync(PowerShell power, string userID, Enum department)
{
var alreadyWhiteListed = WhiteList.ContainsKey(userID) && WhiteList[userID] == department;
if (!alreadyWhiteListed)
{
WhiteList.Add(userID, department)
await power.InvokeAsync()
}
}
现在似乎没有太多重复的代码,而且每个函数做的工作更少,所以它们可能更容易理解
如果我们不想使用Enum
,我们还可以进行其他重构,但这可能已经足够好了。试一试:
public static Dictionary<Building, Func<int, Enum>> mySwitch = new Dictionary<Building, Func<int, Enum>>()
{
{ Building.CaneRidge, n => (CaneRidgeSettings.Departments)n },
{ Building.Carothers, n => (CarothersSettings.Departments)n },
{ Building.CSC, n => (CSCSettings.Departments)n },
{ Building.HQ, n => (HQSettings.Departments)n },
};
private async Task CheckWhiteList(PowerShell power)
{
var history = new KeyValuePair<string, Enum>(Model.UserID, mySwitch[(Building)Model.BuildingSelectedIndex](Model.DepartmentSelectedIndex));
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
}
publicstaticdictionary mySwitch=newdictionary()
{
{Building.CaneRidge,n=>(CaneRidgeSettings.Departments)n},
{Building.Carothers,n=>(CarothersSettings.Departments)n},
{Building.CSC,n=>(cscssettings.Departments)n},
{Building.HQ,n=>(HQSettings.Departments)n},
};
专用异步任务检查白名单(PowerShell电源)
{
var history=newkeyvaluepair(Model.UserID,mySwitch[(Building)Model.BuildingSelectedIndex](Model.DepartmentSelectedIndex));
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
}
如果它对你有用,请让我知道,我可以再解释一下。不过我现在必须跑步。试试看:
public static Dictionary<Building, Func<int, Enum>> mySwitch = new Dictionary<Building, Func<int, Enum>>()
{
{ Building.CaneRidge, n => (CaneRidgeSettings.Departments)n },
{ Building.Carothers, n => (CarothersSettings.Departments)n },
{ Building.CSC, n => (CSCSettings.Departments)n },
{ Building.HQ, n => (HQSettings.Departments)n },
};
private async Task CheckWhiteList(PowerShell power)
{
var history = new KeyValuePair<string, Enum>(Model.UserID, mySwitch[(Building)Model.BuildingSelectedIndex](Model.DepartmentSelectedIndex));
if (!WhiteList.Contains(history))
{
WhiteList.Add(history.Key, history.Value);
await power.InvokeAsync();
}
}
publicstaticdictionary mySwitch=newdictionary()
{
{Building.CaneRidge,n=>(CaneRidgeSettings.Departments)n},
{Building.Carothers,n=>(CarothersSettings.Departments)n},
{Building.CSC,n=>(cscssettings.Departments)n},
{Building.HQ,n=>(HQSettings.Departments)n},
};
专用异步任务检查白名单(PowerShell电源)
{
var history=newkeyvaluepair(Model.UserID,mySwitch[(Building)Model.BuildingSelectedIndex](Model.DepartmentSelectedIndex));
如果(!WhiteList.Contains(历史))
{
添加(history.Key、history.Value);
等待电源。InvokeAsync();
}
}
如果它对您有效,请让我知道,我可以进一步解释。不过我现在必须运行。您能展示一下您的“通用静态词典”代码吗?我想提出这样的解决方案,但想先看看您是如何做到的。public static dictionary WhiteList=new dictionary();所有的字典都是这样的,只是使用基本Enum类作为TValues,为什么看起来很糟糕?因为唯一可行的方法就是把它放在一个switch语句中,如上图所示,有很多重复的代码。我不确定是否有更好的方法来处理这样的情况。我已经发布了一个没有开关和密码的答案