我的情景:
public class EntityBase
{
public int ID { get; set; }
[Required()]
public string Name { get; set; }
//And this is what is getting me
//I want a "Type" enum
}
然后派生类将具有不同的枚举,它们将分配给Type。
public class AnimalEntity : EntityBase
{
//Type would have an 'animal type' value: Land, Sea or Air
//Implementation code would do something like:
// myAnimal.Type = AnimalType.Land
}
public class PersonEntity : EntityBase
{
//Type would have a 'person type' value: Doctor, Lawyer or Engineer
//Implementation code would do something like:
// myPerson.Type = PersonType.Lawyer
}
public class MonsterEntity : EntityBase
{
//Type would have a 'monster type' value: Goblinoid, Undead
}
所以,最重要的问题是我想做什么,对吧?我正在尝试创建一个基本存储库类,它将返回按类型分组的实体。我的所有实体都会有某种“类型”,我想创建一个通用的“按类型分组”。
public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : EntityBase
{
//Our common GetAsync, GetByIdAsync, and all our other CRUD
//And then something like this:
public IEnumerable<GroupedData<string, T>> GetGroupedByType(string searchTerm)
{
var entities =
from s in DbSet
where (searchTerm == null || s.Name.ToLower().Contains(searchTerm))
group s by s.Type into g
select new GroupedData<string, T> { Key = g.Key.ToString(), Data = g };
return (entities);
}
}
当T是AnimalEntity时,我会使用相应的实体获得Land,Sea和Air组。对于PersonEntity,我会找到Doctor,Lawyer,Engineer团队。
如果我的方法/设计无效或不理想,请告诉我。
答案 0 :(得分:1)
我能想到的两个选择:
首先,最好在此示例中使用generic type parameter(T
):
public class EntityBase<T>
{
public T Type {get;set;}
}
在类型声明中提供该类型:
public class AnimalEntity : EntityBase<AnimalEnum>
{ }
其次,如果您需要更多自由,我通常会使用string
个符号列表:
public class EntityBase
{
public string Type {get;set;}
}
public static class AnimalTypes
{
public const string Dog = "dog";
public const string Cat = "cat";
}
答案 1 :(得分:1)
Enum(请原谅我)是一类二等公民,所以你可能会想到的第一件事就是不能工作:
class EntityBase<T> where T : enum {
public T Type { get; set; }
}
不幸的是它没有编译,你可以考虑用基类替换enum
:
class EntityBase<T> where T : EntityTypeBase {
public T Type { get; set; }
}
在EntityTypeBase
中实现您需要的所有内容(==
和!=
运算符,IConvertible
接口和其他样板文件)。它是很多代码,您还需要在EF中管理它(否则您将无法在查询中使用此类属性,除非您将内存中的所有内容作为对象加载)。您也可以force the use of enum
s(使用运行时检查)但这会破坏EF中的SQL代码生成。
我建议在这种情况下是使用EF知道和理解的类型。您可以使用字符串(如果您愿意)或整数(如本例所示):
class EntityBase
public virtual int Type { get; set; }
}
在派生类中:
class AnimalEntity : EntityBase {
public override int Type {
get { return base.Type; }
set {
if (!Enum.IsDefined(typeof(AnimalType), value))
throw new ArgumentException();
base.Type = (int)value;
}
}
}
通过这种方式,您仍然可以使用PersonType.Layer
和AnimalType.Land
保持一点类型安全性。当然,你需要保持你的枚举同步,没有重复的值(否则group by
不会工作)。
最后请也考虑使用......另一个实体。如果您有另一张表EntityType
:
ID Name ApplicableTo 0 Laywer Person 1 Programmer Person 2 Land Animal ...
你在setter中要做的是检查类型是否适用,你可能没有几个便利类可以按类型对它们进行分组:
public static class PersonType {
public static EntityType Lawyer { get { ... } }
public static EntityType Programmer { get { ... } }
}
IMO 规模更好(更容易添加新项目,您可以将某些行为委托给EntityType
个项目)和更安全比硬编码常量(因为完整性由DB引擎本身授予)。当然,支付价格是EntityType
表中搜索的额外开销(除非你使用一些缓存机制)。