【问题标题】:Return a new instance of the most derived class in a virtual function返回虚函数中派生最多的类的新实例
【发布时间】:2013-02-14 16:03:02
【问题描述】:

我有一个实现 IDataReader 的清洁类,它的作用是过滤 SQL Server 的 DateTime 范围之外的任何 DateTime 值并返回 DBNull(正在馈送此类的输出在SqlBulkCopy 中,我的数据源可以返回 1753 年 1 月 1 日之前的日期)

我的问题是接口的函数之一返回一个新的IDataReader,我希望任何派生类都不需要重写该函数来返回一个新对象本身。这是一个例子

public class SqlServerDataCleaner : IDataReader
{
    public SqlServerDataCleaner(IDataReader dataSource)
    {
        this.dataSource = dataSource;
        //(Snip)
    }

    //(Snip)

    public virtual IDataReader GetData(int i)
    {
        return new SqlServerDataCleaner(dataSource.GetData(i));
    }

}

class SqlServerDataCleanerDerived : SqlServerDataCleaner
{
    public SqlServerDataCleanerDerived (IDataReader dataSource) 
        : base(dataSource)
    {
    }

    //(Snip)

    //Need to return the correct class
    public override IDataReader GetData(int i)
    {
        return new SqlServerDataCleanerDerived (dataSource.GetData(i));
    }

}

有什么方法可以消除对GetData 的覆盖,这样父类将自动在它的GetData 的副本中创建该类的最派生形式(假设所有派生类总是有一个@987654331 @构造函数)?

【问题讨论】:

    标签: c# inheritance constructor overriding


    【解决方案1】:

    反思救援:

    public virtual IDataReader GetData(int i)
    {
      return (IDataReader)Activator.CreateInstance(GetType(), dataSource.GetData(i));
    }
    

    GetType 总是返回当前实例的类型,即,对于 SqlServerDataCleaner 实例,它返回 typeof(SqlServerDataCleaner),对于 SqlServerDataCleanerDerived 实例,它返回 typeof(SqlServerDataCleanerDerived)。您可以将此类型传递给Activator.CreateInstance method

    【讨论】:

    • 这绝对有效,也许这在Stack Overflow Chat(我的雇主阻止)中会更好,但是这似乎不是错误/有异味吗?
    • 反射总是以在编译时失去类型检查的安全性和对性能的小幅影响为代价的。我不确定这是否合理;我可能会在每个类中重复该方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2018-10-14
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多