ExpandoObjeto Expando a tipo anónimo

¿Puedo lanzar ExpandoObject a tipo anónimo?

var anoObj = new { name = "testName", email = "testEmail" }; dynamic expandoObj = new System.Dynamic.ExpandoObject(); // Here I'm populating the expandoObj with same property names/types in anonymoustype(anoObj) // Now, how to convert this ExpandoObject to anonymoustype ? var newObj = (typeof(anoObj)expandoObj); // This doesn't work 

Añadido más tarde

// Esta es mi entidad

 public class Customer { #region Public Properties [ColumnAttribute(Name = "IdColumn")] public string Id { get; set; } [ColumnAttribute(Name = "NameColumn")] public string Name { get; set; } [ColumnAttribute(Name = "AddressColumn")] public string Address { get; set; } [ColumnAttribute(Name = "EmailColumn")] public string Email { get; set; } [ColumnAttribute(Name = "MobileColumn")] public string Mobile { get; set; } #endregion } 

// ———————————————— ————————————-

 public class LookupService { public LookupService () { } public LookupShowable Select(Expression<Func> expression) { var lookupShowable = new LookupShowable(); return lookupShowable; } } public class LookupShowable { public LookupShowable() { } public LookupExecutable Show(Expression<Func> expression) { var lookupExecutable = new LookupExecutable(); return lookupExecutable; } } public class LookupExecutable { public TSelection Execute() { // Here I want to create a new instance of TSelection and populate values from database and return it. } } 

// ———————————————— ————————————–

 // This is How I want to call this from front end... var lookupService = new LookupService(); var lookupSelection = lookupService.Select(C => new { C.Id, C.Name, C.Mobile }).Show(C => new { C.Id, C.Name}).Execute(); string sID = lookupSelection.Id; string sName = lookupSelection.Name; string sMobile = lookupSelection.Mobile; 

No pienses en esta parte intermedia … El propósito de esto es otra …

Mi problema está en el método Execute () en la clase LookupExecutable. No sé cómo crear una nueva instancia del tipo TSelection y asignarle valores. Este tipo de selección de TS es siempre un tipo anónimo.

EDIT: Creo que esta pregunta es un buen ejemplo del problema XY . La solución correcta no necesita preocuparse por ExpandoObject o tipos anónimos, y sería muy probable que estuviera mal si lo hiciera.


Lo estás viendo de la manera equivocada. No necesita crear una instancia de un objeto anónimo, necesita invocar el código que se le pasa en una expresión (que puede o no estar creando un objeto anónimo).

Si puede crear una instancia de TEntitySource , entonces eso es simple: Compile() la Expression que obtuvo en Select() y luego TEntitySource para cada instancia de TEntitySource .

Si no puede crear TEntitySource , aún podría hacerlo reescribiendo la Expression (usando ExpressionVisitor ), de modo que su entrada no sea TEntitySource , sino de algún tipo que tenga. Pero eso requeriría un trabajo de usted.


Respuesta original:

No, eso no funcionará. Simplemente no es así como el casting o los tipos anónimos funcionan en C #.

No puedes elegir entre dos tipos y esperar que funcione. O el objeto que estás lanzando debe ser del tipo al que estás lanzando, o uno de los dos tipos debe especificar un operador de fundición que coincida.

El hecho de que el tipo de destino sea anónimo no cambia nada (excepto que ni siquiera puede intentar convertir directamente a un tipo anónimo, porque no puede nombrarlo; la forma en que está usando typeof() es incorrecto).

El hecho de que el tipo de fuente sea dynamic cambia un poco las cosas. Pero solo en que la búsqueda del operador de DynamicObject.TryCast() se realiza en tiempo de ejecución, no en tiempo de comstackción, e incluso puede crear el operador de DynamicObject.TryCast() en tiempo de ejecución (consulte DynamicObject.TryCast() ). Pero eso es todo, no agrega ningún operador de reparto “mágico”.

La única forma en que puedo imaginar algo como este funcionamiento sería si utilizara una variante de “conversión por ejemplo” y reflexión:

 public T Convert(ExpandoObject source, T example) where T : class { IDictionary dict = source; var ctor = example.GetType().GetConstructors().Single(); var parameters = ctor.GetParameters(); var parameterValues = parameters.Select(p => dict[p.Name]).ToArray(); return (T)ctor.Invoke(parameterValues); } 

Entonces podrías usarlo así:

 var expando = new ExpandoObject(); dynamic dynamicExpando = expando; dynamicExpando.Foo = "SomeString"; dynamicExpando.Bar = 156; var result = Convert(expando, new { Foo = "", Bar = 1 }); 

Tenga en cuenta que en realidad no puede invocar Convert() dinámicamente (al pasarlo a dynamicExpando ), ya que eso significaría que también volvería dynamic .

Use JavaScriptSerializer para convertir ExpandoObject a cualquier tipo de la siguiente manera:

 ..... dynamic myExpandoObject = new ExpandoObject(); var result = ConvertDynamic(myExpandoObject); ..... public T ConvertDynamic(IDictionary dictionary) { var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var obj = jsSerializer.ConvertToType(dictionary); return obj; } 

Esto debería hacer el trabajo.

Aquí tienes un objeto madre de un ExpandoObject.

  var anoObj = new { name = "testName", email = "testEmail" }; dynamic expandoObj = new System.Dynamic.ExpandoObject(); object newObj = expandoObj; 

Pero tenga cuidado, los objetos dynamics son muy costosos en materia de recursos, y lo que está pidiendo no parece tener ningún sentido. Un buen enfoque para lo que está preguntando en los comentarios, suponiendo que tiene que tratar con objetos dynamics y desea hacer algo con ellos:

 dynamic expando = new System.Dynamic.ExpandoObject(); var myObj = new Dictionary(); myObj["myProperty"] = expando.myProperty; 

Cualquier objeto dynamic se convierte fácilmente en un dictado escrito.

¡Espero que ayude!