使用反射和泛型改进代码

Improving code with reflection and generics

对于下面的代码,我如何使用反射和泛型来提高它的可读性? 这是很多重复的代码,但我对这些概念还是陌生的。 “dl”是一个接口,但我不确定为什么我无法使用 .getType().getProperties() 访问我想要的属性,它 returns 一个空列表。

if (entity == "SERVICE")
{
    if (filter == "Active == 1")
    {
        foreach (var service in dl.Services.List().Where(x => x.Active).OrderBy(x => x.Name))
            tmpReturn.Add(service.ID, service.Name);

        return tmpReturn;
    }

    foreach (var service in dl.Services.List().OrderBy(x => x.Name))
        tmpReturn.Add(service.ID, service.Name);

    return tmpReturn;
}

if (entity == "CAMPAIGN")
{
    if (filter == "Active == 1")
    {
        foreach (var campaign in dl.Campaigns.List().Where(x => x.Active).OrderBy(x => x.Name))
            tmpReturn.Add(campaign.ID, campaign.Name);

        return tmpReturn;
    }

    foreach (var campaign in dl.Campaigns.List().OrderBy(x => x.Name))
        tmpReturn.Add(campaign.ID, campaign.Name);

    return tmpReturn;
}

if (entity == "AGENT")
{
    if (condition == "Active != ")
    { 
        if (value == "1")
        { 
            foreach (var agent in dl.Agents.List().OrderBy(x => x.Name))
                tmpReturn.Add(agent.ID, agent.Name);

            return tmpReturn;
        }

        foreach (var agent in dl.Agents.List().Where(x => x.Active).OrderBy(x => x.Name))
            tmpReturn.Add(agent.ID, agent.Name);

        return tmpReturn;
    }
    else if (condition == "Active == ")
    {
        if (value == "1")
        {
            foreach (var agent in dl.Agents.List().Where(x => x.Active).OrderBy(x => x.Name))
                tmpReturn.Add(agent.ID, agent.Name);

            return tmpReturn;
        }

        foreach (var agent in dl.Agents.List().OrderBy(x => x.Name))
            tmpReturn.Add(agent.ID, agent.Name);

        return tmpReturn;
    }
}

我认为您不需要反射或泛型: (我没有在以下代码片段中编写类型,因为我不能总是从您的代码中推断出它们。)

List getTmpReturn(list, bool isActive){
    if (isActive){
        foreach (var item in list.List().Where(x => x.Active).OrderBy(x => x.Name))
             tmpReturn.Add(item.ID, item.Name);
    }
    else {
        foreach (var item in list.List().OrderBy(x => x.Name))
            tmpReturn.Add(item.ID, item.Name);
    }
    return tmpReturn;
}

switch(entity):
    case "SERVICE":
        return getTmpReturn(dl.Services, filter == "Active == 1");
    case "CAMPAIGN":
        return getTmpReturn(dl.Campaigns, filter == "Active == 1");
    case "AGENT":
        bool isActive = (condition == "Active != " && value != "1") || (condition == "Active == " && value == "1");
        return getTmpReturn(dl.Agents, isActive);

由于不同实体不实现通用接口,我们使用 ValueTuples 作为中间结果。我不确定 ID 类型是什么。我在这里假设 int,但您可以轻松更改它。

IEnumerable<(int ID, string Name, bool Active)> source;
bool filterByActive;
switch (entity) {
    case "SERVICE":
        source = dl.Services.List().Select(x => (x.ID, x.Name, x.Active));
        filterByActive = filter == "Active == 1";
        break;
    case "CAMPAIGN":
        source = dl.Campaigns.List().Select(x => (x.ID, x.Name, x.Active));
        filterByActive = filter == "Active == 1";
        break;
    case "AGENT":
        source = dl.Agents.List().Select(x => (x.ID, x.Name, x.Active));
        filterByActive = condition == "Active != " && value != "1" ||
                         condition == "Active == " && value == "1";
        break;
    default:
        throw new NotImplementedException();
}
if (filterByActive) {
    source = source.Where(x => x.Active);
}
return source
    // .OrderBy(x => x.Name)       Not for Dictionary!
    .ToDictionary(x => x.ID, x => x.Name);

我们的想法是 return 一个代表数据源的枚举和一个布尔值,告诉我们是否必须在 switch 语句中进行过滤。然后可以在此数据源上执行所有其他操作。

我们可以通过单独应用 Where 来组合枚举。

使用 LINQ 扩展方法 ToDictionary() 而不是在循环中添加单个元素可以进一步简化事情。请注意,如果您要向字典中添加内容,则对项目进行排序无效。