我让这个班作为我的存储库:
public class Repository<T> where T : class, new()
{
public T GetByID(int id)
{
//Code...
}
}
但有几个案例我不想离开课堂。默认公共构造函数(例如某些需要某些逻辑的特定模型属性),如下所示:
public class Person
{
public CPersonID PersonID { get; private set; }
//This shouldn't exist outside Person, and only Person knows the rules how to handle this
public class CPersonID
{
internal CPersonID() { }
}
}
由于new()
约束,这使得存储库模板类无效。
我想做这样的事情:
public class Repository<T> where T : class
{
//This function should be created only when the T has new()
public GetByID(int id) where T : new()
{
}
//And this could be the alternative if it doesn't have new()
public GetByID(T element, int id)
{
}
}
我有什么方法可以做到这一点吗?
修改:Get
方法示例:
public IList<T> GetAll()
{
IList<T> list = new List<T>();
using(IConnection cn = ConnectionFactory.GetConnection())
{
ICommand cm = cn.GetCommand();
cm.CommandText = "Query";
using (IDataReader dr = cm.ExecuteReader())
{
while(dr.Read())
{
T obj = new T(); //because of this line the class won't compile if I don't have the new() constraint
//a mapping function I made to fill it's properties
LoadObj(obj, dr);
list.Add(obj);
}
}
}
return list;
}
答案 0 :(得分:2)
不,你不能这样做。
必须在引入泛型参数的位置指定所有约束,在本例中为类级别。
因此,您有两种选择:
, new()
作为约束,限制使用存储库类来使用具有公共无参数构造函数的类型注意,如果类型没有有效的构造函数,那么第2点可能会失败(在运行时)。
你无法让编译器创建一个类,其中调用特定方法的能力是有条件的,即。 “如果类型有构造函数,我只能调用GetByID。”
答案 1 :(得分:2)
正如Lasse V. Karlsen已经回答的那样,这不是直接可能的。但是,你可以非常接近,足够接近实际目的。
给定public class Repository<T> where T : class
,您无法定义仅在T
具有无参数构造函数时才存在的实例方法。你不需要那个。你需要repository.GetByID(3)
才能工作。如果GetByID
是实例方法,但是如果它是扩展方法,那么这可以起作用,扩展方法可以向T
添加需求。
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
...
}
}
请注意,如果已经存在同名的实例方法,则扩展方法不起作用,因此如果您使用此方法,则需要GetByID
的两个重载都是扩展方法,而不仅仅是这一个
实际逻辑属于Repository
类,但您可以转发:
public class Repository<T> where T : class
{
internal T GetByIDImpl(int id, Func<T> factory)
{
...
}
}
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
return repo.GetByIDImpl(id, () => new T());
}
public T GetByID(this Repository<T> repo, T element, int id) where T : class
{
return repo.GetByIDImpl(id, () => element);
}
}
答案 2 :(得分:0)
如果您希望将其作为编译时约束,则可以执行
public class Class<T> where T : class
{
public void Method<U> where U : T, new()
{
// ...
}
}
但这有一个缺点,你必须做
new Class<HasConstructor>().Method<HasConstructor>();
因为不会隐式拾取类型。优点是以下内容无法编译:
new Class<NoConstructor>().Method<NoConstructor>();