С# Преобразование динамической строки в существующий класс
В приложении Windows, используя С#, у меня есть модуль отчетности, который будет полагаться на классы для заполнения отчетов. Однако будет много сообщений, и я не хочу, чтобы их кодовое обозначение для каждого.
Поток будет таким:
В редакторе отчетов отчет будет присвоен класс (т.е. "Приложения" ) в виде строки.
Когда пользователь выбрал отчет для запуска, код будет получать данные из SQL-запроса.
Код возьмет данные и узнает, в какой класс помещать данные.
Затем отчет возьмет класс и заполнит отчет данными из класса.
Вот моя дилемна, как мне сделать динамический код так, чтобы код преобразовал назначенный класс в правильный объект класса?
Пример:
gVar = Report;
(gVar.ReportClass)oClass = new gVar.ReportClass;
Ответы
Ответ 1
Используйте Type.GetType
(в частности, одна из перегрузок (например, Type.GetType(string)
), который принимает параметр string
), чтобы загрузить экземпляр Type
для соответствующего класса, а затем используйте Activator.CreateInstance
или Type.GetConstructor
в этом экземпляре Type
для создания экземпляра экземпляра.
Итак, что-то вроде
Type type = Type.GetType(assemblyQualifiedName);
object instance = Activator.CreateInstance(type);
Обратите внимание, что вы должны передать имя сборки сборки, если только этот тип не указан в mscorlib или в текущей исполняемой сборке.
Кроме того, Activator.CreateInstance
предполагает существование конструктора по умолчанию. Если конструктор по умолчанию отсутствует или вам нужно передать некоторые параметры конструктору, вам придется использовать overload Activator.CreateInstance
, что позволяет указать параметры конструктора или Type.GetConstructor
для загрузки соответствующего конструктора.
Ответ 2
Вы можете использовать отражение, чтобы сделать это. Если вы дадите им все похожие базовые классы или интерфейс, вы можете сделать что-то вроде:
myBaseReport report = (myBaseReport)System.Activator.CreateInstance("MyAssemblyName", myClassStringWithFullNameSpace).Unwrap();
Это войдет в сборку named и загрузит класс напрямую. Строка класса - это полное имя рассматриваемого типа, что-то вроде MyGlobalNamespace.MyCustomNameSpace.MySpecificType
. Это позволит вам создать отчет определенного типа и поместить его в тип базового класса или тип интерфейса.
Ответ 3
Вы будете хорошо использовать неявные операторы:
Это звучит хорошо для ваших нужд, потому что это позволяет вам делать что-то вроде:
Orange orange = new Orange();
Apple apple = (Apple)orange;
Или:
string appleJson = "{ Weight: '2kg' }";
Apple apple = appleJson;
Неявный оператор десериализует эту сериализованную строку apple-JSON в обычный объект, напечатанный Apple.
Я не знаю, если это то, что вы ищете, и я надеюсь, что никто не будет участвовать в голосовании, если это доступная функция С#.
EDITED: я неправильно понял вопрос. Спасибо комментаторам, даже кто проголосовал за мой ответ, потому что я был неправ.
ИЗМЕНИТЬ 2:
Взятие другого подхода Activator/Reflection, который кажется правильным для автора текущего вопроса, и, прочитав его другой вопрос о том, "как заполнить тогда свойства полученного экземпляра отчета", я хочу предложить некоторое решение.
Вы можете определить какой-либо атрибут, такой как "ReportPropertyAttribute" без свойств, конструктор по умолчанию и проверить с отражением для свойств, отмеченных предлагаемым атрибутом.
Или вы можете определить какой-либо файл конфигурации или конфигурации (обычный API конфигурации .NET), поэтому вы можете определить "известные типы отчетов" и "какие свойства являются аргументами или параметрами некоторого типа отчета".
Я надеюсь, что это соответствует вашим потребностям!
Ответ 4
Немного непонятно, что именно вы просите здесь. Однако, на основании того, что я читаю, у вас есть строка, содержащая имя типа, и вы хотите создать экземпляр класса на основе этого? Вы можете использовать отражение для этого...
Type type = Type.GetType(strTypeName);
object oClass = Activator.CreateInstance(type);