重写派生类中的公共属性

本文关键字:属性 派生 重写 | 更新日期: 2023-09-27 18:22:48

在一个旧项目中,我们使用了一个第三方程序集,该程序集的类具有带有一些硬编码信息的属性:

public string ConnectionString
{
    get
    {
        string[] fullDbName = new string[5];
        fullDbName[0] = "Data Source=";
        fullDbName[1] = this.dbServer;
        fullDbName[2] = ";Initial Catalog=";
        fullDbName[3] = this.FullDbName;
        fullDbName[4] = ";Integrated Security=SSPI;Pooling=false";
        return string.Concat(fullDbName);
    }
}

我需要能够自己构建连接字符串。因此,我试图创建一个隐藏原始属性的派生类,但它似乎不起作用:

public class SqlServerRestorerExstension : SQLServerRestorer
{
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown)
    {
        ConnectionString = connectionstring;
    }
    public string ConnectionString { get; private set; }
}

当我没有访问第三方代码的权限时,有可能以任何方式实现这一点吗?

重写派生类中的公共属性

正如其他人所指出的,您可以使用new关键字来隐藏基本成员属性。然而,请注意,这并不能神奇地将ConnectionString属性变成多态函数,即,如果您有这样的东西:

public class A 
{
    public string CString { get { return "a"; } }
}
public class B : A
{
    public new string CString { get { return "b"; }}
}

你这样做:

A a = new B();
Console.WriteLine(a.CString);

然后,您仍然会看到控制台上打印的"a"。事实上,new关键字只是阻止编译器发出关于隐藏基类成员的警告。它不会在运行时更改代码的行为。

你可以尝试使用Decorator模式并包装SQLServerRestorer,但如果这也不起作用,恐怕你运气不好了。

您需要使用new:指示要"替换"此属性

public new string ConnectionString
{
   get { return "My custom connection string"; }
}

显然,您可以扩展它来实现自己的set,即使只是为了使用自动实现的访问器。关于new"版本控制"的文档可以在这里找到,但特别是:

使用new关键字告诉编译器您的定义隐藏了基类中包含的定义。这是默认行为。

您正在查找new关键字:

public class SqlServerRestorerExstension : SQLServerRestorer
{
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown)
    {
        ConnectionString = connectionstring;
    }
    public new string ConnectionString { get; private set; }
}

您想覆盖该方法,但似乎无法覆盖:

使用重写修饰符可以修改方法、属性、索引器或事件。重写方法提供了从基类继承的成员的新实现。被重写声明重写的方法称为重写的基方法。被重写的基方法必须与重写方法具有相同的签名。

不能重写非虚拟或静态方法。重写的基方法必须是虚拟的、抽象的或重写的。

尽管其他人指出你可以使用新的修饰语,但我认为这对你没有好处:

在同一成员上同时使用new和override是错误的,因为这两个修饰符具有互斥的含义。新的修改器将创建一个具有相同名称的新成员,并使原始成员隐藏起来。重写修饰符扩展了继承成员的实现。

对我来说,这听起来像是任何使用基本(第三方)类型的代码都会调用旧属性——这是一个等待发生的混乱!