2012-03-09 38 views
3

我有一个名为GenericDao有可能通过<T>超类的子类?

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>(); 
     } 
    } 
} 

回答

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对象之外,您不必更改调用代码。

1

这是一件好事,你的尝试不起作用,你会引入一个错误,如果它。

假设我有两个变量a,bEmpresaDaoaEmpresa父母一起创建,并且b用父母Assessoria初始化。由于ab属于同一类型,所以应该可以在其他地方使用其中一个。假设Assessoria但不是Empresa有一个方法assess()。但您预期b.parentAssessoria,因此您想要致电b.parent.assess(),但不能致电a.parent.assess()这意味着ab不应该是同一类型。

的解决方案取决于你是否会叫.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)你有时会打电话给.parent.assess() EmpresaDao类中。那么你应该做的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。我相信我的主要依然有效。