我有一些使用 LINQ-to-SQL 创建的实体。其中六个实体(主要在下拉列表中表示值)实现了我称为IValue
. 我这样做是因为 UI 层将不得不考虑几个特殊情况——特别是,如果记录上的原始值已被标记为已删除,将显示什么。
ListAllXXX
存储库为这些人提供了多种方法。所有这些都返回类型为适当实体类型的通用列表。一个例子:
public static List<ContactType> ListAllContactTypes(DeletedOptions getDeleted)
{ /* requisite code */ }
ContactType
确实实现IValue
了,当然。
还有另一组服务旨在实际检索特定于 UI 的列表。因此,基本模式是:
// One of these for each entity type
public static List<IValue> GetContactTypeList(ContactType target)
{
List<IValue> ret = LovRepository.ListAllContactTypes(DeletedOptions.NoDeleted);
PrepList(ret, target);
return ret;
}
// All of the above methods use this guy
private static void PrepList(List<IValue> list, IValue targetEntity)
{
list.Insert(0, new DummyValue() { Description = "Add New ... ", ID = 0 });
if (targetEntity != null && !(list.Contains(targetEntity))
list.Add(new DummyValue() { Description = "[deleted]", ID = -1 });
}
(我可能应该注意到这DummyValue
是我创建的一个简单的类,它也实现了IValue
,它的全部目的是充当“添加新”和“删除”菜单选项。)
所有这一切都是因为我不想编写几十行几乎相同的代码——这就是我认为我们有协方差的全部原因。
此处编写的代码无法编译。我试过手动投到List<IValue>
就ListAllContactTypes
行了;编译,但在运行时失败并出现无效的强制转换异常。
我怎样才能到达我想去的地方?对接口使用泛型变量是否有限制?如果是这样,有没有简单的方法解决它?如果不是,我是否会沦为编写一堆高度重复但略有不同的代码?(我真的很想避免。)
这很可能是重复的,但我的 Google-fu 现在让我失望了。如果是,请相应地投票关闭。(如果是这样的话,我会投票赞成!)