Можете ли вы изменить значение свойства Name типа во время выполнения?

#c# #reflection

#c# #отражение

Вопрос:

Возможно ли изменить / переопределить свойство Name типа?

Учитывая определение класса:

 class Sample
{}
 

Можете ли вы изменить typeof(Sample).Name возвращаемое значение?

Я использую пользовательскую библиотеку сериализации, которая буквально используется typeof(T).Name в их исходном коде:

 writer.WriteStartElement(typeof(T).Name);
writer.WriteValue(item);
writer.WriteEndElement();
 

Комментарии:

1. когда вы говорите name, вы имеете в виду имя переменной?

2. @CodeCaster «потому что какой-то код, который я не могу контролировать, использует это, чтобы сериализовать это значение». это контекст

3. Для получения информации я изучил .Name реализацию, и она в основном завершается неуправляемой функцией : [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("QCall", CharSet=CharSet.Unicode)] private static extern void ConstructName(RuntimeTypeHandle handle, TypeNameFormatFlags formatFlags, StringHandleOnStack retString) . Так что, если есть способ подделать это, он полностью секретный и недокументированный.

4. Разве вы не можете использовать класс обработки XML для последующего изменения сгенерированного XML?

5. хорошая идея; xslt было бы довольно тривиально переименовать один элемент

Ответ №1:

Нет, вы не можете изменить свойство .Name a Type во время выполнения. Однако большинство библиотек сериализации позволяют вам иметь некоторый контроль над обработкой имен, либо предоставляя пользовательскую «привязку» (и т.д.), Либо добавляя к типу атрибуты, указывающие предпочтительное имя для использования (примечание: большинство библиотек, разрешающих атрибуты, также позволяют предоставлять имя во время выполненияконфигурация библиотеки сериализации).

Тогда важный вопрос: какая библиотека сериализации используется здесь?

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

Комментарии:

1. что, если класс уже существует TheNameIWant ? Тогда я не могу переименовать Sample или создать тип во время выполнения…

2. @last вы можете, в другом пространстве имен.

Ответ №2:

Я не знаю никакого способа выполнить такую задачу. CLR делает то же самое с объектами marshalled by ref, но я сомневаюсь, что это позволит вам «переименовать» ваш класс или его свойство (поле) таким образом.

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

Ответ №3:

Из вашего вопроса вы упомянули, что хотите управлять именем во время сериализации

Если вы хотите изменить имя во время сериализации, вы можете использовать следующие атрибуты

 [DataContract(Name = "NewName")] 
[XmlRoot("NewName")] 
class Sample
{
}
 

Комментарии:

1. это полностью зависит от того, какая библиотека сериализации используется; подход к использованию сильно различается

Ответ №4:

Что касается сериализации XML с использованием XmlSerialization библиотеки в BCL, вы можете переопределить имя элемента xml, которое будет сгенерировано, используя следующий атрибут:

 [XmlElement("SomeOtherName")]
public class Sample{...}
 

Комментарии:

1. это полностью зависит от того, какая библиотека сериализации используется; подход к использованию сильно различается

2. @MarcGravell Да, я конкретно говорю о XmlSerialization библиотеке.

3. Спасибо, но это не вариант для меня, поскольку я использую пользовательскую библиотеку сериализации, которая использует ‘typeof (T).Name’ в своем исходном коде…

4. @lastr2d2 в этом случае ваши варианты: 1) смириться с этим, 2) изменить имя class Sample в вашем коде, 3) добавить отдельный тип DTO, который вы используете только для сериализации, 4) написать много-много кода для автоматической генерации DTO с разными именами. Я подозреваю, что я бы выбрал «2» или «3».