С# Преобразование динамической строки в существующий класс

В приложении 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);