我有以下两种方法从我的数据库中获取数据并返回一个填充的SelectList对象(包括一个“All”选项值),然后我将其传递给我的视图。问题是它们几乎完全相同,除了它们都访问不同的存储库对象并且它们具有不同的ID名称(StatusId和TeamId)。我认为有机会将它们重构为一个接受存储库作为参数的方法,并以某种方式计算出ID名称应该是什么,可能是通过使用反射或某种lambda表达式,但我不知道如何实现这一目标。
private SelectList GetStatusSelectList(int selectedStatusId)
{
List<MemberStatus> statusList = _memberStatusRepository.All().ToList();
statusList.Insert(0, new MemberStatus {StatusId = 0, Name = "All"});
var statusSelectList = new SelectList(statusList, "StatusId", "Name", selectedStatusId);
return statusSelectList;
}
private SelectList GetTeamSelectList(int selectedTeamId)
{
List<MemberTeam> teamList = _memberTeamRepository.All().ToList();
teamList.Insert(0, new MemberTeam { TeamId = 0, Name = "All" });
var teamSelectList = new SelectList(teamList, "TeamId", "Name", selectedTeamId);
return teamSelectList;
}
任何人都可以帮助弄清楚如何将这些重构为单一方法吗?
答案 0 :(得分:3)
嗯,这是我能提出的最通用的,但它需要MemberStatus
和MemberTeam
实施IIdentifiable
,我不知道是否可以申请你的情况。如果是这样,这将是要走的路。
private SelectList GetList<T>(IRepository repository, int id, string name)
where T : IIdentifiable, new()
{
List<IIdentifiable> list = repository.All().ToList();
list.Insert(0, new T() { Name = name, Id = id });
var statusSelectList = new SelectList(list, "Id", "Name", id);
}
接口代码
interface IIdentifiable
{
int Id { get; set; }
string Name { get; set; }
}
答案 1 :(得分:2)
您可以尝试以下方法:
private SelectList GetStatusSelectList(int selectedStatusId)
{
return GetGenericSelectList<MemberStatus>(selectedStatusId, _memberStatusRepository.All().ToList(), "StatusId");
}
private SelectList GetTeamSelectList(int selectedTeamId)
{
return GetGenericSelectList<MemberTeam>(selectedTeamId, _memberTeamRepository.All().ToList(), "TeamId");
}
private SelectList GetGenericSelectList<T>(int selectedTeamId, List<T> list, string idFieldName) where T : new()
{
var firstItem = new T();
(firstItem as dynamic).Name = "All";
var l = new List<T>(list);
l.Insert(0, firstItem);
return new SelectList(l, idFieldName, "Name", selectedTeamId);
}
此解决方案并不理想,并且依赖于某些约定(例如,您的所有项目都应具有Name
属性)。然而,这似乎是一个不错的开始。它可以通过使用表达式而不是属性名进一步改进 - 这将允许通过编译时间检查来更改属性名称。
答案 2 :(得分:1)
从我看到的,除了确定要使用的正确存储库之外,将其重构为单个方法的主要障碍是new MemberStatus
和new MemberTeam
调用。
要想出一个优雅的解决方案,您需要更多的基础架构配置 - 基本上您需要根据类型解析正确的存储库,并且您希望某种工厂构建对象实例。 / p>
以下内容将代码重构为单个方法,但不是(在我看来)比您已有的单独方法更好:
private SelectList GetSelectList<T>(int selectedId, Func<List<T>> repoAllFunc, Func<T> typeNewFunc, string idName)
{
List<T> list = repoAllFunc();
list.Insert(0, typeNewFunc());
var selectList = new SelectList(list, idName, "Name", selectedId);
return selectList;
}
然后您可以这样称呼它:
var memberStatusSelectList =
GetSelectList<MemberStatus>(
id,
() => _memberStatusRepository.All().ToList(),
() => new MemberStatus {StatusId = 0, Name = "All"});
答案 3 :(得分:1)
你可以疯狂地使用一点界面并执行以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication3
{
public class MemberStatus : IDefault<MemberStatus>
{
public int StatusId { get; set; }
public string Name { get; set; }
public MemberStatus Default
{
get { return new MemberStatus() { StatusId = 0, Name = "All" }; }
}
public string IdName
{
get { return "StatusId"; }
}
}
public class MemberTeam : IDefault<MemberTeam>
{
public int TeamId { get; set; }
public string Name { get; set; }
public MemberTeam Default
{
get { return new MemberTeam() { TeamId = 0, Name = "All" }; }
}
public string IdName
{
get { return "TeamId"; }
}
}
public interface IDefault<T>
{
T Default { get; }
string IdName { get; }
}
public interface IRepository<T>
{
IEnumerable<T> All();
}
public class MemberStatusRepository : IRepository<MemberStatus>
{
public IEnumerable<MemberStatus> All()
{
return new[] {
new MemberStatus(),
new MemberStatus()
};
}
}
public class MemberTeamRepository : IRepository<MemberTeam>
{
public IEnumerable<MemberTeam> All()
{
return new[] {
new MemberTeam(),
new MemberTeam()
};
}
}
public class DataAccessLayer
{
IRepository<MemberStatus> _memberStatusRepository;
IRepository<MemberTeam> _memberTeamRepository;
public DataAccessLayer()
{
_memberStatusRepository = new MemberStatusRepository();
_memberTeamRepository = new MemberTeamRepository();
}
public SelectList<TResult> GetTeamSelectList<TRepository, TResult>(TRepository repo, int selectedTeamId)
where TRepository : IRepository<TResult>
where TResult : IDefault<TResult>, new()
{
List<TResult> teamList = repo.All().ToList();
var dummyobj = new TResult();
teamList.Insert(0, dummyobj.Default);
var teamSelectList = new SelectList<TResult>(teamList, dummyobj.IdName, "Name", selectedTeamId);
return teamSelectList;
}
}
class Program
{
static void Main(string[] args)
{
var dal = new DataAccessLayer();
SelectList<MemberStatus> results = dal.GetTeamSelectList<IRepository<MemberStatus>, MemberStatus>(new MemberStatusRepository(), 5);
Console.WriteLine();
Console.Read();
}
}
public class SelectList<TResult>
{
public SelectList(List<TResult> teamList, string p, string p_2, int selectedTeamId)
{
}
}
}
如果您可以在界面中定义静态属性会很好,但是因为您不能依赖于创建虚拟对象。
答案 4 :(得分:0)
如果IRepository
添加了一些“功能”,您将获得更清晰的代码。
而不是All()
有一个SingleRecordsWithAllRecord()
方法来处理前两行。然后让存储库定义自己的DataValueField
和DataTextField
。
private SelectList GetSelectList(IRepository repo, int selectedId)
{
var selectListAll = repo.SingleRecordsWithAllRecord().ToList();
return new SelectList(selectListAll,
repo.DataValueField,
repo.DataTextField,
selectedId);
}