2010-02-09 25 views
5

Tenemos código XML almacenado en un solo campo de base de datos relacional para evitar los problemas de la base de datos Entidad/Atributo/Valor, sin embargo, no quiero que esto arruine mi Dominio de modelado, DTO y repositorio. No puedo evitar el contenido de EAV/CR, pero puedo elegir cómo almacenarlo. La pregunta es ¿cómo lo usaría?¿Cómo se define un objeto C# en tiempo de ejecución?

¿Cómo podría convertir los metadatos XML en una clase/objeto en tiempo de ejecución en C#?

Por ejemplo:

XML describiría que tenemos una receta de comida que tiene varios atributos, pero suelen ser similares, y uno o más atributos acerca de hacer la comida. La comida en sí puede ser literalmente cualquier cosa y tener cualquier tipo de preparación loca. Todos los atributos se buscan y pueden vincular a la información nutricional existente.

// <-- [Model validation annotation goes here for MVC2] 
public class Pizza { 
    public string kind {get; set;} 
    public string shape {get; set;} 
    public string city {get; set;} 
    ... 
} 

y en el ActionMethod:

makePizzaActionMethod (Pizza myPizza) { 
    if (myPizza.isValid()) { // this is probably ModelState.isValid()... 
     myRecipeRepository.Save(myPizza); 
     return View("Saved"); 
    } 
    else 
     return View(); 
} 
+0

Suponiendo que el repositorio no sería pizza específica. –

+0

¿El XML tiene un esquema? Luego puede usar el esquema para generar código. Si no, entonces necesitas un lenguaje dinámico, no C#. –

+0

Podemos tener un esquema para el XML. La clase de receta en realidad no cambia una vez que existe, pero las nuevas clases de recetas se pueden crear sobre la marcha. Diría aproximadamente 15-20 clases de recetas por tipo de cliente, y tenemos muchos tipos diferentes de clientes, a todos les gusta comer. –

Respuesta

9

¿Es ExpandoObject lo que estás buscando?

representa un objeto cuyos miembros pueden añadirse dinámicamente y eliminado en tiempo de ejecución.

+0

Wow. Ahora esa es una buena aplicación de conocimiento para un problema en particular. Voy a dejar que la pregunta avance un poco, pero esta respuesta es muy buena. –

+0

Encuentro esto muy perturbador, personalmente. Pero supongo que este no es el lugar para debatir los méritos de esta "cosa". –

+0

Bienvenido al valiente mundo nuevo de dynamic C#. –

1

EDIT: Esto no se refiere a la pregunta de su creador original.

Creo que esto puede ser posible usando XAML. Generaría un archivo XAML, y luego load it dynamically using XamlReader.Load() crearía un objeto en tiempo de ejecución con las propiedades que quiero.

Hay un artículo interesante para leer sobre el tema XAML as an object serialization framework here. Para obtener más información sobre XAML namespaces see here.

+2

@cdiggins: -1: No puedo imaginarme cómo XAML ayudará. Eliminaré el voto negativo si ayudas a mi imaginación. –

+0

Agregó algunas aclaraciones. Puede crear objetos dinámicos con XamlReader.Load(), ¿no va a funcionar esto en el caso del Dr. Zim? ¿O me estoy perdiendo algo? – cdiggins

+0

¿Puedes dar un ejemplo? Porque no te creo –

3

Consulte el espacio de nombres System.Reflection.Emit.

Se comienza con una clase de AssemblyBuilder AppDomain.CurrentDomain

AssemblyBuilder dynAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly("dynamic.dll", 
                      AssemblyBuilderAccess.RunAndSave); 

Desde allí se tiene que construir una ModuleBuilder, desde donde se puede construir una TypeBuilder.

Consulte la referencia AssmblyBuilder para ver un ejemplo.

Puede guardar el ensamblaje generado o simplemente puede usarlo en la memoria. Tenga en cuenta, sin embargo, que se verá pesado en la reflexión para utilizar estos tipos dinámicos.

EDIT:

A continuación se muestra un ejemplo de cómo repetir las propiedades:

AssemblyName aName = new AssemblyName("dynamic"); 
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave); 
ModuleBuilder mb = ab.DefineDynamicModule("dynamic.dll"); 
TypeBuilder tb = mb.DefineType("Pizza"); 
//Define your type here based on the info in your xml 
Type theType = tb.CreateType(); 

//instanciate your object 
ConstructorInfo ctor = theType.GetConstructor(Type.EmptyTypes); 
object inst = ctor.Invoke(new object[]{}); 

PropertyInfo[] pList = theType.GetProperties(BindingFlags.DeclaredOnly); 
//iterate through all the properties of the instance 'inst' of your new Type 
foreach(PropertyInfo pi in pList) 
    Console.WriteLine(pi.GetValue(inst, null)); 
+1

Todavía no veo cómo se podría utilizar una clase de este tipo, ya que el código no conoce las propiedades adicionales. –

+0

Puede iterar a través de las Propiedades del nuevo tipo usando la clase de Tipo asociada. Agregaré un ejemplo arriba. –

Cuestiones relacionadas