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语句中,如上图所示,有很多重复的代码。我不确定是否有更好的方法来处理这样的情况。我已经发布了一个没有开关和密码的答案