我有一个加载参考数据的数据访问类。每种类型的实体都将执行它自己的存储过程并返回特定于该实体类型的结果集。然后我有一个方法将返回值从数据表映射到实体。所有实体类型都具有相同的Code和Name公共属性,如何使此方法通用以处理一种类型的实体?像这样的东西是假定但属性导致错误。
private static T MapDataReaderToEntity<T>(IDataReader reader)
{
var entity = typeof (T);
entity.Code = SqlPersistence.GetString(reader, "Code");
entity.Name = SqlPersistence.GetString(reader, "Name");
return entity;
}
我会用这样的话来称呼它。
_sourceSystem = MapDataReaderToEntity<SourceSystem>(_reader);
答案 0 :(得分:4)
您可以拥有一个定义这些属性的接口,然后让您的实体类实现该接口:
public interface IEntity
{
string Code { get; set; }
string Name { get; set; }
}
现在,您可以为方法添加通用约束:
public static T MapDataReaderToEntity<T>(IDataReader reader) where T : IEntity, new()
{
T entity = new T();
// More code here...
}
请注意,您还需要new()
约束来实际构建新实体;它表示任何泛型类型参数都有一个无参数构造函数。
答案 1 :(得分:3)
如果您的实体实现了定义了Code和Name属性的接口,您可能会使用以下内容:
private static T MapDataReaderToEntity<T>(IDataReader reader)
where T : IEntity, new()
{
T entity = new T(); // typeof(T) would return the System.Type, not an instance!
entity.Code = SqlPersistence.GetString(reader, "Code");
entity.Name = SqlPersistence.GetString(reader, "Name");
return entity;
}
如果没有接口,编译器无法知道Code
或Name
属性。您需要恢复使用Reflection或动态代码,或其他一些不太理想的机制来在运行时而不是在编译时确定这些属性。
答案 2 :(得分:2)
您需要向MapDataReaderToEntity<T>
添加type constraint,以确保任何T实现Code和Name属性设置器,以及无参数构造函数。
答案 3 :(得分:1)
如果您的所有实体都有Code
和Name
属性,我建议让他们实现一个属性为ICodedEntity
和Code
的接口Name
,然后定义你的方法
private static T MapDataReaderToEntity<T>(IDataReader reader) where T : ICodedEntity, new()
{
var entity = new T();
...
}
然后您将编译的代码。