2011-02-02 8 views
10

Dentro de una aplicación de Windows, usando C#, tengo un módulo de informes que dependerá de las clases para rellenar los informes. Sin embargo, habrá muchos informes y no quiero tener que codificarlos para cada uno.C# Convertir cadenas dinámicas a la clase existente

El flujo será como tal: En el editor de informes, al informe se le asignará una clase (es decir, "Aplicaciones") como una cadena. Cuando el usuario seleccionó el informe para ejecutar, el código adquirirá los datos de una consulta SQL. El código tomará los datos y descubrirá en qué clase colocar los datos. Luego el informe tomará la clase y completará el informe con los datos de la clase.

Aquí está mi dilema, ¿cómo hago que el código sea dinámico para que el código convierta la clase asignada en el objeto de clase adecuado?

ejemplo en mente:

gVar = Report; 
(gVar.ReportClass)oClass = new gVar.ReportClass; 
+0

Gracias Anthony Olvidé poner esa última parte en las etiquetas de código – mattgcon

+0

No soy la misma persona que publicó esa pregunta, no sabía cómo expresar correctamente mi pregunta para que no apareciera – mattgcon

+0

Eso no es un problema mate . Acabo de agregar el duplicado para que se puedan vincular. Verificaría esa pregunta. Debería responder a su pregunta (si la entiendo correctamente). –

Respuesta

7

Uso Type.GetType (específicamente una de las sobrecargas (por ejemplo, Type.GetType(string)) que toma un parámetro string) para cargar la instancia de Type para la clase apropiada, y luego usar Activator.CreateInstance o Type.GetConstructor en esa instancia de Type para instanciar una instancia.

Por lo tanto, algo así como

Type type = Type.GetType(assemblyQualifiedName); 
object instance = Activator.CreateInstance(type); 

Tenga en cuenta que debe pasar la assembly qualified name menos que el tipo está en mscorlib o el conjunto se está ejecutando actualmente.

Además, Activator.CreateInstance asume la existencia de un constructor predeterminado. Si no hay un constructor predeterminado, o si necesita pasar algunos parámetros al constructor, tendrá que usar un overload de Activator.CreateInstance que le permite especificar los parámetros del constructor, o Type.GetConstructor para cargar el constructor apropiado.

+0

aquí hay una pregunta que simplemente me vino a la cabeza, cuando instalo la clase de la cadena, supongo que no hay forma de colocar los datos en las propiedades respectivas dentro de la clase de forma dinámica. (es decir, reportclass.clientname = dt ["CLIENTNAME"]. ToString()) – mattgcon

+0

Si sabe que su objeto tendrá dicha propiedad (supongamos que todos los objetos que está creando dinámicamente se derivan de una clase base común o una común interfaz, puede convertir a esa clase base o interfaz y luego acceder a la propiedad a través de esa clase base o interfaz). Así que supongamos que todos sus objetos derivan de una clase llamada 'Informe' y' Informe' tiene una propiedad llamada 'NombreCliente'. Entonces podría decir 'Informe r = (Informe) Activador.CrearInstancia (tipo); r.ClientName = dt ["CLIENTNAME"]. ToString(); '. Alternativamente, puede usar el reflejo para establecer la propiedad. ¿Tener sentido? – jason

+0

Hmmmm, eso es un problema porque no hay una clase base común o una interfaz común y por lo que recuerdo sobre la reflexión tendré que decirle qué propiedades estoy buscando haciendo referencia a ella en una cadena. – mattgcon

2

Vas a estar bien mediante operadores implícitos:

Eso suena bien para sus necesidades, ya que le permite hacer algo como:

Orange orange = new Orange(); 
Apple apple = (Apple)orange; 

O bien:

string appleJson = "{ Weight: '2kg' }"; 
Apple apple = appleJson; 

Un operador implícito deserializará esa cadena Apple-serializada JSON en un objeto normal escrito por Apple.

No sé si esto es lo que estás buscando, y espero que nadie vote si esta es una característica de C# que está disponible.

EDITADO: He entendido mal la pregunta. Gracias a los comentaristas, incluso a quienes votaron negativamente mi respuesta, porque estaba equivocado.

EDIT 2:

Tomar otros Activador/enfoque de reflexión - que parece ser el más adecuado para el autor de la pregunta actual -, y la lectura de su otra pregunta sobre "cómo llenar a continuación las propiedades de instancia de informe obtenido ", Quiero sugerir alguna solución.

Puede definir algún atributo como "ReportPropertyAttribute" sin propiedades, constructor predeterminado e inspeccionar con reflejo propiedades que están marcadas con el atributo sugerido.

O puede definir algún archivo de configuración o sección de configuración (API de configuración .NET regular), para que pueda definir "tipos de informes conocidos" y "qué propiedades son argumentos o parámetros de algún tipo de informe".

Espero que esto esté en la línea de sus necesidades!

+0

Esto supone que ya conoce el tipo. La forma en que la pregunta me lee es que el tipo puede variar y no conocerá el tipo real hasta el tiempo de ejecución. Esto no funcionará para eso. –

+0

Bueno, con la menor cantidad de información que proporcionó, traté de pensar que él está en la otra situación, porque dice "No quiero repetir el código de conversión de A a B". –

+0

Yo dije "al informe se le asignará una clase (es decir"Aplicaciones") como una cadena "y" ¿cómo hago que el código sea dinámico para que el código convierta la clase asignada en el objeto de clase adecuado? " – mattgcon

2

No está exactamente claro exactamente lo que está pidiendo aquí. Sobre la base de lo que "m lectura, sin embargo, usted tiene una cadena que contiene un nombre de tipo y que desea crear una instancia de una clase basada en eso? Puede utilizar la reflexión para hacer esto ...

Type type = Type.GetType(strTypeName); 
object oClass = Activator.CreateInstance(type); 
4

Se puede utilizar reflejo de hacerlo si se les da toda una clase de base similar o interfaz, se puede hacer algo como:..

myBaseReport report = (myBaseReport)System.Activator.CreateInstance("MyAssemblyName", myClassStringWithFullNameSpace).Unwrap(); 

Esto irá en el conjunto con nombre y cargar la clase directamente a la cadena de clase es el nombre completo del tipo en cuestión, algo así como MyGlobalNamespace.MyCustomNameSpace.MySpecificType. Esto le permitirá crear el tipo específico de informe y ponerlo en el tipo de clase base o tipo de interfaz mi.

+0

Desafortunadamente, no hay dos clases de informes iguales, por lo que no se creó una clase base o interfaz. – mattgcon

+0

@mattgcon - Entonces será mejor que escriba como objeto al realizar este tipo de creación de instancias. Y cualquier método al que pase tendrá que aceptar el objeto. –

+0

@JoelEtherton: He votado porque mencionaste el nombre de la clase CON FULL NAMESPACE que deja claro su uso. – Rama

Cuestiones relacionadas