我有一个名为GenericDao的类
internal class GenericDao<T> : IGenericDao<T> {
}
两类对象:
public class Empresa {
}
public class Assessoria : Empresa {
}
我有一个EmpresaDao:
public class EmpresaDao {
private GenericDao<Empresa> parent { get; set; }
public EmpresaDao() {
this.parent = new GenericDao<Empresa>();
}
}
如何使用子类Assessoria实例化GenericDao?我这样做了,但没有工作:
public class EmpresaDao {
private GenericDao<Empresa> parent { get; set; }
public EmpresaDao(Type type) {
if (type == typeof(Assessoria)) {
this.parent = new GenericDao<Assessoria>();
} else {
this.parent = new GenericDao<Empresa>();
}
}
}
答案 0 :(得分:2)
总之,你不能,真的。但是,如果使用非通用的基本接口,或者使用C#4并使用通用的基本接口,但具有协变或逆变(根据需要)类型参数,则可以作弊。对于第一种情况:
interface IGenericDaoBase {
}
interface IGenericDao<T> : IGenericDaoBase {
}
public class EmpresaDao {
private IGenericDaoBase parent { get; set; }
public EmpresaDao(Type type) {
// same as before
}
}
不可否认,重新考虑您的设计可能会更好。也许EmpresaDao可以采用一个通用参数本身,可以这样使用:
public class EmpresaDao<T> where T : Empresa {
private GenericDao<T> parent { get; set; }
public EmpresaDao() {
this.parent = new GenericDao<T>();
}
}
编辑:事实上,我越是想到它,我越相信后一种解决方案就是要走的路。构造函数中的type参数与类签名上的type参数具有相同的作用。因此,除了传入泛型参数而不是Type对象之外,您不必更改调用代码。
答案 1 :(得分:1)
你的尝试不起作用是件好事,如果有的话,你会引入一个bug。
假设我有a
类型的变量b
,EmpresaDao
。使用a
父级启动Empresa
,并使用b
父级初始化Assessoria
。由于a
和b
属于同一类型,因此应该可以在任何地方使用一个代替另一个。假设Assessoria
但不Empresa
有方法assess()
。但您希望b.parent
为Assessoria
,因此您需要致电b.parent.assess()
,但无法致电a.parent.assess()
,这意味着a
和b
不应该首先是相同类型的。
解决方案取决于您是否会拨打.parent.assess()
:
a)如果你永远不会在.parent.assess()
类中调用EmpresaDao
,那么让父编译的时间类型始终为Empresa
。这是一个解决方案:
public class EmpresaDao
{
private Empresa parent {get; set; }
public EmpresaDao(Func<Empresa> parentConstructor)
{
this.parent = parentConstructor();
}
}
static main()
{
var withEmpresaParent = new EmpresaDao(() => new Empresa());
var withAssessoriaParent = new EmpresaDao(() => new Assessoria());
..
}
b)您有时会在EmpresaDao课程中拨打.parent.assess()
。那么你应该让EmpresaDao变得通用,就像@siride说的那样:
public class EmpresaDao<T> where T : Empresa
{
private T parent {get; set;}
}
但是,仍然需要在调用.parent.assess()
之前对父进行运行时检查。这意味着您的设计中仍然存在问题。但是没有足够的信息来决定什么。也许.assess()
方法应该是私有的,不能从外部调用(即Assessoria
应该是Empresa
上的装饰器:子类但具有相同的接口)也许“Empresa
持有EmpresaDao
“和”Assessoria
持有EmpresaDao
“应该是两个不同的类别。 (可能实现相同的接口)
编辑:现在我意识到,在我的解决方案中,我错误地将父Empresa或Assessoria的类型改为GenericDao或GenericDao。我相信我的主要仍然有效。