Вот моя ситуация:
У меня есть сторонний компонентный элемент управления, который я успешно унаследовал, и теперь я делаю некоторую кумуляцию.
Часть этой настройки заключается в изменении значений DefaultValues некоторых свойств, которые у него есть.
Пока все прошло хорошо, но в этом элементе управления есть несколько классов "Sub", которые я хочу изменить и по умолчанию.
Под классами "Sub" я имею в виду: пусть говорят, что мой элемент управления называется SomeControl, поэтому он имеет свойства в нем, но он также имеет свойство, которое может расширяться, например: SomeControl.Rows, свойство.Rows возвращает RowCollection, у которого есть свой собственный свойства. Итак, это то, что я имею в виду под классом "Sub" (пожалуйста, поправьте меня, если у вас есть лучший термин для этого)
В любом случае, если я хочу изменить некоторые значения DefaultValues в классе RowCollection, мне тоже нужно наследовать его. Пропаганда заключается в том, что RowCollection Ctor является внутренним, поэтому я не могу наследовать этот класс.
Итак, есть ли другой способ изменить атрибут DefaultValue для свойства в классе, который я не могу наследовать?
Может быть, через отражение?
Мне нужно изменить его для экземпляра (объекта), который у меня есть - один экземпляр, а не для класса вообще.. (поскольку после создания из него 1 объекта больше не создается..)
спасибо
Реферат: Я не думаю, что это можно сделать с помощью рефлексии, но вот как я это сделаю:
Сначала получите имущество, которое вы хотите:
var defValAttr = typeof (SomeControl.RowCollection)
.GetProperty("yourProperty")
.GetCustomAttributes(typeof(DefaultValueAttribute), false)
.First()
as DefaultValueAttribute;
DefaultValueAttribute имеет свойство.Value, которое является readonly. Чтобы изменить его, вам нужно снова отразить изменение частного поля.value:
var valueField= typeof (DefaultValueAttribute)
.GetField("value", BindingFlags.NonPublic
| BindingFlags.GetField
| BindingFlags.Instance);
valueField.SetValue(defValAttr, yourNewDefaultValue);
Я сам не проверял это, но, насколько я знаю, это не сработает. Объекты, возвращаемые GetCustomAttributes, не являются фактическими атрибутами; вы можете получить значения реальных атрибутов таким образом, но вы не можете их изменить. (см. Могут ли атрибуты добавляться динамически в С#?)
Однако, даже если это будет работать, оно изменит значение DefaultValue для всех экземпляров SomeControl.Rows, независимо от того, находятся ли они в вашем настраиваемом контроле или в базовом элементе управления. Невозможно изменить только значение DefaultValue одного экземпляра, так как это значение сохраняется только один раз для каждого класса, а не один раз для каждого экземпляра. Было бы очень расточительно, если бы была копия каждого атрибута для каждого экземпляра объекта.
Поэтому в заключение я не думаю, что есть способ сделать это.
В качестве альтернативы вы можете декомпилировать стороннюю сборку и добавить свою собственную сборку с InternalsVisibleTo, чтобы вы могли получить доступ к внутреннему конструктору.
Добавление: Возможно, все еще есть способ сделать это, в зависимости от того, какой атрибут вы хотите изменить. Атрибуты, доступные через отражение, как я сказал, вероятно неизменны. Однако редактор визуальной студии и вся модель компонента WPF фактически используют TypeDescriptor для управления атрибутами поверх базовой системы атрибутов, встроенной в язык. Вы можете изменить атрибуты, используемые TypeProvider, и если код позже будет обращаться к атрибутам через TypeDescriptor, он может видеть измененные значения.
Далее не тестируется следующее:
var instanceOfRow = instanceOfYourControl.Rows;
var defValAttr = TypeDescriptor
.GetProperties(instanceOfRow)["yourProperty"]
.Attributes[typeof (DefaultValueAttribute)]
as DefaultValueAttribute;
var valueField= typeof (DefaultValueAttribute)
.GetField("value", BindingFlags.NonPublic
| BindingFlags.GetField
| BindingFlags.Instance);
valueField.SetValue(defValAttr, yourNewDefaultValue);
DefaultValue
? Можете ли вы объяснить, почему вам нужно заменить его, а не присваивать значения свойств не по умолчанию вашему одному измененному экземпляру?