Установка значения частного свойства в конструкторе наследуемого класса - PullRequest
1 голос
/ 17 декабря 2009

У меня есть базовый класс из внешней библиотеки, который я не могу изменить - вот соответствующий фрагмент:

public class BaseClass
{
     List<string> _values;
     public Values { get { return _values; } }
}

Я наследую BaseClass и хочу установить _values ​​для класса, который наследуется от List (T) в конструкторе:

public InheritingClass : BaseClass
{
     public InheritingClass():base()
     {
          //set base._values = new InhertingList<string>(); ?
     }
}

Какой лучший способ установить base._values ​​там? Есть ли способ узнать, какая частная переменная выбирается из значений, и установить, что в случае, если частная переменная будет переименована в будущем?

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

Ответы [ 7 ]

7 голосов
/ 17 декабря 2009

Сохранение приватности по определению должно предотвратить этот точный сценарий.

Наилучшим вариантом будет реализация защищенного установщика:

public class BaseClass
{
     public Values { 
        get { return _values; }
        protected set { _values = value; }
     }
}

Таким образом, ваш InheritingClass имеет доступ к установщику и может выполнять:

this.Values = new InhertingList<string>(); 

Но поскольку вы не можете изменить базовый класс, технически это возможно сделать с помощью отражения (в сценарии полного доверия). Я не рекомендую этот подход, хотя:

FieldInfo field = typeof(BaseClass).GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic );
field.SetValue(this, this.Values = new InhertingList<string>() );

Опасность выполнения того, что вы пытаетесь, между прочим, заключается в том, что вы собираетесь изменить реализацию, определенную в BaseClass, на то, что вы предоставляете. Очень легко вводить тонкие ошибки, поскольку вы (целенаправленно) «ломаете» детали реализации в базовом классе.

Я бы попробовал переосмыслить ваш алгоритм и посмотреть, есть ли другой способ обойти эту проблему.

2 голосов
/ 17 декабря 2009

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

Edit: Может быть возможно разобрать ваш BaseClass и изменить его реализацию. Булочка, тогда тебе, возможно, придется разобрать всю библиотеку.

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

1 голос
/ 18 декабря 2009

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

Конечно, в зависимости от уровня доверия, под которым работает ваше приложение, вы можете установить приватную переменную с помощью рефлексии, но это действительно будет хаком, чтобы обойти то, что действительно является проблемой в проекте. *

1 голос
/ 17 декабря 2009

Обычно, когда у вас нет свойства с доступным установщиком, предоставленным для поля, это означает, что вам не следует изменять это поле где-либо, кроме BaseClass - если создатель класса BaseClass хотел бы, чтобы вы в состоянии изменить это поле, он выставил бы свойство с защищенным установщиком или что-то в этом роде. Так что вообще не рекомендуется взламывать его.

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

Что касается других ответов: он написал: «У меня есть базовый класс из внешней библиотеки, который я не могу изменить».

0 голосов
/ 09 февраля 2014

Вы всегда можете использовать ключевое слово "new", но унаследованный метод будет игнорироваться, если класс приведен обратно к его базовому объекту

public InheritingClass : BaseClass
{
     public InheritingClass()
     {
          Values = new InhertingList<string>(); ?
     }

     public new List<string> Values { get; private set; }
}

Для доступа к закрытым полям вы можете использовать Reflection, но, поскольку поле является закрытым, я не уверен, что наследующий класс выиграет от изменения типа закрытого поля.

public InheritingClass : BaseClass
{
   private static FieldInfo _valueField = typeof(BaseClass).GetField("_values", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

   public InheritingClass()
   {
        _valueField.SetValue(this, new InhertingList<string>());
   }
}

http://msdn.microsoft.com/en-us/library/6z33zd7h(v=vs.110).aspx

0 голосов
/ 17 декабря 2009

Обычно, когда поля не имеют методов-мутаторов, вы используете конструктор класса для создания экземпляра объекта (и его соответствующих полей).

BaseClass base = new BaseClass(List<string> yourList);
0 голосов
/ 17 декабря 2009

Нет, нет способа сделать то, что вы ищете. Частные переменные должны быть частными, а именно: они не могут быть видны или изменены каким-либо кодом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...