Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 它';<;中超类的s可能通过子类;T>;?_C#_Oop_Nhibernate_Polymorphism - Fatal编程技术网

C# 它';<;中超类的s可能通过子类;T>;?

C# 它';<;中超类的s可能通过子类;T>;?,c#,oop,nhibernate,polymorphism,C#,Oop,Nhibernate,Polymorphism,我有一个名为GenericDao的类 internal class GenericDao<T> : IGenericDao<T> { } 我有一个问题: public class EmpresaDao { private GenericDao<Empresa> parent { get; set; } public EmpresaDao() { this.parent = new GenericDao<Empresa

我有一个名为GenericDao的类

internal class GenericDao<T> : IGenericDao<T> {
}
我有一个问题:

public class EmpresaDao {

    private GenericDao<Empresa> parent { get; set; }

    public EmpresaDao() {
        this.parent = new GenericDao<Empresa>();
    }
}
公共类EmpresaDao{
私有GenericDao父级{get;set;}
公共行政区(){
this.parent=new GenericDao();
}
}
如何使用子类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>();
        }
    }
}
公共类EmpresaDao{
私有GenericDao父级{get;set;}
公共EmpresaDao(类型){
如果(类型==类型(评估)){
this.parent=new GenericDao();
}否则{
this.parent=new GenericDao();
}
}
}

简而言之,你真的不能。但是,如果使用非泛型的基本接口,或者使用C#4并使用泛型的基本接口,但带有协变或逆变(取决于需要)类型参数,则可能会有一些欺骗。对于第一种情况:

interface IGenericDaoBase {
}

interface IGenericDao<T> : IGenericDaoBase {
}

public class EmpresaDao {
    private IGenericDaoBase parent { get; set; }
    public EmpresaDao(Type type) {
        // same as before
    }
}
接口IGenericDaoBase{
}
接口IGenericDao:IGenericDaoBase{
}
公共类EmpresaDao{
私有IGenericDaoBase父项{get;set;}
公共EmpresaDao(类型){
//和以前一样
}
}
诚然,重新思考您的设计可能会更好。也许EmpresaDao可以采用通用参数本身,其使用方式如下:

public class EmpresaDao<T> where T : Empresa {
    private GenericDao<T> parent { get; set; }
    public EmpresaDao() {
        this.parent = new GenericDao<T>();
    }
}
公共类EmpresaDao其中T:Empresa{
私有GenericDao父级{get;set;}
公共行政区(){
this.parent=new GenericDao();
}
}

编辑:事实上,我想得越多,就越相信后一种解决方案是可行的。构造函数中的类型参数正在执行与类签名上的类型参数相同的角色。因此,您不必对调用代码进行太多更改,只需传入一个泛型参数而不是类型对象。

您的尝试不起作用是一件好事,如果它起作用,您将引入一个bug

假设我的变量
a
b
都是
EmpresaDao
类型<代码>a由
Empresa
父项初始化,而
b
Assessoria
父项初始化。由于
a
b
属于同一类型,因此应该可以在任何地方使用其中一个来代替另一个。假设
Assessoria
而不是
Empresa
有一个方法
assessment()
。但是您希望
b.parent
成为
Assessoria
,因此您希望调用
b.parent.assessment()
,但您不能调用
a.parent.assessment()
,这意味着
a
b
首先不应该属于同一类型

解决方案取决于您是否调用
.parent.assessment()

a) 如果您永远不会在
EmpresaDao
类中调用
.parent.assessment()
,则让父类的编译时类型始终为
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());
    ..
}
但是,在调用
.parent.assessment()
之前,仍然需要对父级进行运行时检查,这意味着您的设计中仍然存在一些错误。但目前还没有足够的信息来决定要做什么。可能
.assessment()
方法应该是私有的,不能从外部调用(即
Assessoria
应该是
Empresa
:子类上的装饰器,但具有相同的接口)可能“
Empresa
holding
EmpresaDao
”和“
Assessoria
holding
EmpresaDao
”应该是两个不同的类。(可能实现相同的接口)

编辑:现在我意识到,在我的解决方案中,我错误地将父Empresa或Assessoria类型设置为GenericDao或GenericDao。不过,我相信我的主要观点仍然有效

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());
    ..
}
public class EmpresaDao<T> where T : Empresa
{
    private T parent {get; set;}
}