2009-11-12 11 views
11

Tengo el siguiente en C#:¿Cómo generar una instancia de un tipo desconocido en tiempo de ejecución?

string typename = "System.Int32"; 
string value = "4"; 

las tesis de dos cadenas se deben tomar para generar un objeto del tipo especificado con el valor especificado ...

resultado debe ser:

object o = CreateUnknownType(typename, value); 
... 
Int32 test = (Int32)o; 
+4

Y tu pregunta es? ¿Por qué tratar de crear un desconocido si va a lanzarlo a un tipo conocido más tarde? – Lazarus

+6

La pregunta es: ¿Cómo generar una instancia de un tipo desconocido en tiempo de ejecución? No importa por qué o no, solo quiero saber si es posible – haze4real

+2

Eso es fácil, entonces sí, es posible. ¿Es practicable? Probablemente no. ¿No fue razonable pedir un contexto cuando tu ejemplo no tiene sentido? – Lazarus

Respuesta

20

¿Esto es lo que estás pensando?

object result = Convert.ChangeType("4", Type.GetType("System.Int32")); 
+0

sí, eso es todo, gracias – haze4real

1

Su lógica parece un poco defectuosa aquí. Obviamente, si está transfiriendo el objeto directamente al tipo actual, entonces debe conocer el tipo para comenzar.

Si hay algo más que falta en esta pregunta por favor elabore y tal vez hay una respuesta más adecuada que simplemente: "Esto no tiene mucho sentido".

0

Parece un trabajo para Int32.Parse (cadena). Pero para estar de acuerdo con los demás parece que esto es "único" y uno probablemente debería pensar en guantes.

15

Como se ha indicado, esto es demasiado amplio y no puede ser resuelto en general.

Estas son algunas opciones:

Type type = Type.GetType(typename); 
object o = Activator.CreateInstance(type); 

Esto creará una instancia del tipo que typename está describiendo. Llama al constructor sin parámetros de ese tipo. (Desventaja: No todos los objetos tienen un constructor sin parámetros Además, esto establece el estado del objeto utilizando value..)

Type type = Type.GetType(typename); 
object o = Activator.CreateInstance(type, new[] { value }); 

Esto creará una instancia del tipo que typename está describiendo. Llama a un constructor de ese tipo que acepta un parámetro del tipo string. (Desventaja: No todos los objetos tienen un constructor como, por ejemplo, Int32 no tiene un constructor tal manera que experimentará una excepción de tiempo de ejecución..)

Type type = Type.GetType(typename); 
object o = Convert.ChangeType(value, type); 

Este intentará convertir la cadena value a una instancia de la tipo requerido. Esto puede llevar a InvalidCastException s sin embargo. Por ejemplo, Convert.ChangeType("4", typeof(FileStream)) obviamente fallará, como debería.

De hecho, este último ejemplo (crear una instancia del tipo FileStream con su estado inicial determinado por la cadena "4") muestra cuán absurdo es el problema general. Hay algunas construcciones/conversiones que simplemente no se pueden hacer.

Es posible que desee volver a pensar el problema que está tratando de resolver para evitar este pantano.

+0

tal vez debería, gracias por explicarme las posibilidades ... – haze4real

3

Creación de una instancia de un tipo que se conocen por su nombre (y que debe tener un constructor por defecto):

string typeName = "System.Int32"; 
    Type type = Type.GetType(type); 
    object o = Activator.CreateInstance(type); 

análisis de un valor a partir de una cadena será, obviamente, sólo trabajar para un conjunto limitado de tipos.Se podría

  • uso Convert.ChangeType como se sugiere por PhilipW
  • o tal vez crear un Dictionary<Type,Func<string,object>> que mapea los tipos conocidos para analizar conocido funciones
  • o el uso de reflexión para invocar el Parse (String) en el tipo, asumiendo que hay uno:

    string valueText = "4"; 
        MethodInfo parseMethod = type.GetMethod("Parse"); 
        object value = parseMethod.Invoke(null, new object[] { valueText }); 
    
  • o tal vez puede utilizar la infraestructura proporcionada por .NET modelo de componente. Se puede recuperar el convertidor tipo de un componente y utilizar así:

    TypeConverter converter = TypeDescriptor.GetConverter(type); 
        object value = converter.ConvertFromString(valueText); 
    
0

Después de usar:

Type type = Type.GetType(typename); 

probar este método de extensión:

public static class ReflectionExtensions 
{ 
    public static T CreateInstance<T>(this Type source, params object[] objects) 
     where T : class 
    {    
     var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray()); 
     return cons == null ? null : (T)cons.Invoke(objects); 
    } 
} 

Esperanza esto ayuda.

1

¿Quizás tiene un conjunto de diferentes tipos, todos los cuales implementan una interfaz conocida?

Por ejemplo, si tiene varios controles de usuario diferentes y quiere cargar uno de ellos en un contenedor, cada uno podría implementar IMyWobblyControl (una interfaz conocida) pero es posible que no sepa hasta el momento de ejecución cuál de ellos cargar, posiblemente leyendo cadenas de algún tipo de archivo de configuración.

En ese caso, tendrá que usar la reflexión para cargar el tipo real a partir de algo así como el nombre completo del ensamblaje, y luego convertirlo en su tipo conocido para usarlo.

Por supuesto, es necesario asegurarse de que el código se ocupa de reparto no válido, el montaje no se encuentra y cualquiera de las otras excepciones que puedan venir a través de algo tan inestable como esta ...

0

Aquí hay una específica ejemplo del problema que involucra a las Federaciones SQL de Azure ... que divide los datos en db's separados de acuerdo con un rango clave.

Los tipos clave gama son:

SQL/.Net tipo SQL/CLR .Net

INT/SqlInt32/Int32, Anulable

BIGINT/SqlInt64/Int64 Nullable

UNIQUEIDENTIFIER/SqlGuid/Guid, Nullable

VARBINARY (n), n max 900/SqlBytes, SqlBinary/byte []

Idealmente, un C# función PARAM podría tomar cualquier tipo SQL .NET o tipo CLR .Net pero de colocar en una sola categoría de tipo está bien.

¿Sería un param tipo "objeto" el camino a seguir? Y, ¿hay una forma factible de identificar el tipo y convertirlo en consecuencia?

El concepto es algo así como:

public void fn (objeto obj, cadena fedName, DISTNAME cadena, bool filteringOn)

{

... averiguar qué tipo obj es asegurar es uno de los tipos aceptables ...

cadena clave = obj.toString();

return string.Format ("USE FEDERATION {0} ({1} = '{2}') CON RESET, FILTERING = {3}", fedName, distName, key, (filteringOn? "ON": " APAGADO"));

}

Aunque el valor de parámetro es arrojado a la cadena, se refundió/comprobado en el lado del servidor SQL para validarlo en el lado aplicación que se desea.

Cuestiones relacionadas