2008-11-24 8 views
10

Este es un ejemplo artificial, pero digamos que he declarado objetos:Programatically usando una cadena como nombre de objeto cuando una instancia de un objeto

CustomObj fooObj; 
CustomObj barObj; 
CustomObj bazObj; 

y tengo una matriz de cadenas:

string[] stringarray = new string[] {"foo","bar","baz"}; 

Cómo puedo acceder de manera programática y crear instancias de esos objetos usando la matriz de cadenas, iterar usando algo así como un foreach:

foreach (string i in stringarray) { 
    `i`Obj = new CustomObj(i); 
} 

Esperamos que la idea de que estoy tratando de transmitir es claro. ¿Es esto posible en C#?

Gracias de antemano.

+0

Tal vez, usted está buscando para asignar objetos a las variables de instancia en tiempo de ejecución o simplemente crear objetos de forma dinámica? –

Respuesta

31

Necesita ser claro en su mente acerca de la diferencia entre un objeto y una variable. Los objetos en sí mismos no tienen nombres. Los nombres de las variables se deciden en tiempo de compilación. No puede acceder a las variables mediante un nombre determinado en el tiempo de ejecución, excepto a través de la reflexión.

Parece que realmente que desea es una Dictionary<string, CustomObj>:

Dictionary<string, CustomObj> map = new Dictionary<string, CustomObj>(); 

foreach (string name in stringArray) 
{ 
    map[name] = new CustomObj(name); 
} 

A continuación, puede acceder a los objetos utilizando el indexador al diccionario.

Si realmente está tratando de establecer los valores de las variables en función de su nombre en el momento de la ejecución, tendrá que usar la reflexión (consulte Type.GetField). Tenga en cuenta que esto no funcionará para las variables locales.

+4

Creo que esta respuesta debería ganar el premio "Intuiting What The Customer REALALL Wanted". Buena respuesta – ScottTx

+0

¿Y si el 'CustomObj' no tiene un constructor? – Jnr

+0

@Jnr: Entonces la pregunta no se aplica, dado que el OP está en una situación donde * hay * un constructor. Básicamente, "cómo se construyen las instancias" y "cómo se hace un seguimiento de las instancias en una colección" son preocupaciones totalmente ortogonales. –

4

No se puede.

Puede colocarlos en un diccionario:

Dictionary<String, CustomObj> objs = new Dictionary<String, CustomObj>(); 

foreach (string i in stringarray) 
{ 
    objs[i] = new CustomObj(i); 
} 

pero eso es tan bueno como se pone.

Si almacena los objetos en los campos en su clase, como esto:

public class SomeClass 
{ 
    private CustomObj fooObj; 
    private CustomObj barObj; 
    private CustomObj bazObj; 
} 

A continuación, se puede llegar a ellos a través de la reflexión. Avíseme si esa es la ruta que desea tomar.

0

Esto es posible utilizando la reflexión si las variables son variables miembro de la clase, pero es terriblemente lento para nada más que aplicaciones muy especializadas. Creo que si lo detallado lo que estamos tratando de hacer, podemos ofrecer mejores sugerencias. Es muy raro que haya un caso en el que deba acceder a una variable como lo hace.

0

Una opción es la ruta totalmente dinámico, según this article, donde se especifica un bloque de código en una cadena y luego compilar/ejecuta desde dentro de su programa

0

Otra opción, menos flexible, pero más simple es a través de Activator.CreateInstance - en el que pide un nuevo objeto que se creará - no va a asignar a las variables dinámicas, pero es que necesita?

2

se puede utilizar una función de búsqueda:

public static Control FindControl(string controlId, Control container) 
    { 
     if (container.ID == controlId) 
      return container; 

     foreach (Control control in container.Controls) 
     { 
      Control c = FindControl(controlId, control); 
      if (c != null) 
       return c; 
     } 
     return null; 
    } 

y por lo que recibirá su control, con base en el índice de la siguiente manera: cuadro de texto Nombre = (Cuadro de texto) FindControl (string.Concat ("Cuadro de texto", índice .ToString()), esto); Espero que esto ayude.

+0

ID no es propiedad de Control. Puede usar la propiedad Name: "if (container.Name == controlId)" – Jan

0

@jotte: Muchas gracias por esa función. ¡Lo usé y funciona! Excepto que necesita cambiar container.ID por container.Name

continuación, sólo tiene que usar algo como (este ejemplo es para casilla de verificación, pero cualquier tipo de variable podría funcionar):

cadena Prueba = "cbACn "+ i.ToString(); CheckBox cbTest = (CheckBox) FindControl (Test, gbACSCAT); if (cbTest! = Null) { cbTest.Checked = true; }

2

uso this.Controls.Find (Control_Name, true) [0] ... sólo recuerda a echarlo

Cuestiones relacionadas