使用反射和泛型改进代码
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()
而不是在循环中添加单个元素可以进一步简化事情。请注意,如果您要向字典中添加内容,则对项目进行排序无效。
对于下面的代码,我如何使用反射和泛型来提高它的可读性? 这是很多重复的代码,但我对这些概念还是陌生的。 “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()
而不是在循环中添加单个元素可以进一步简化事情。请注意,如果您要向字典中添加内容,则对项目进行排序无效。