Переопределить публичное свойство из производного класса - PullRequest
6 голосов
/ 07 февраля 2012

В старом проекте мы используем стороннюю сборку с классом, у которого есть свойство с некоторой жестко закодированной информацией:

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

Можно ли добиться этого каким-либо образом, когда у меня нет доступа к стороннему коду?

Ответы [ 4 ]

7 голосов
/ 07 февраля 2012

Как уже отмечали другие, вы можете использовать ключевое слово 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);

Тогда вы все равно увидите «а», напечатанное на консоли.На самом деле ключевое слово new просто не дает компилятору выдать предупреждение о скрытии члена базового класса.Это не меняет поведения кода во время выполнения.

Вы можете попробовать использовать шаблон Decorator и обернуть SQLServerRestorer, но если это тоже не сработает, вам не повезло, ябоится.

4 голосов
/ 07 февраля 2012

Вам нужно будет указать, что вы хотите «заменить» это свойство, используя new:

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

Очевидно, что вы можете расширить это для реализации своих собственных set, даже если просто использовать автоматически реализованные средства доступа. Документацию по «версиям» с new можно найти здесь , но конкретно:

Использование ключевого слова new сообщает компилятору, что ваше определение скрывает определение, содержащееся в базовом классе. Это поведение по умолчанию.

3 голосов
/ 07 февраля 2012

Вы ищете ключевое слово 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; }
}
0 голосов
/ 07 февраля 2012

Вы хотите переопределить метод, но кажется, что вы не можете:

Используйте модификатор переопределения, чтобы изменить метод, свойство, индексатор илисобытие.Метод переопределения предоставляет новую реализацию члена, унаследованного от базового класса.Метод, переопределенный объявлением переопределения, называется переопределенным базовым методом.Переопределенный базовый метод должен иметь ту же сигнатуру, что и метод переопределения.

Нельзя переопределить не виртуальный или статический метод.Переопределенный базовый метод должен быть виртуальным, абстрактным или переопределенным.

Хотя другие отмечают, что вы можете использовать модификатор new , я не думаю, что он будет вам полезен:

Ошибочно использовать как новый, так и переопределение для одного и того же члена, поскольку оба модификатора имеют взаимоисключающие значения.Модификатор new создает новый элемент с тем же именем и делает его скрытым.Модификатор переопределения расширяет реализацию для унаследованного члена.

Для меня это звучит как любой код, использующий базовый (сторонний) тип, вызовет старое свойство - это беспорядок, просто ожидающий произойти!

...