utilice una sirve que programacion para palabra objeto new metodos instancia crear and c# .net reflection

una - ¿Cómo copiar el valor de la clase X a la clase Y con el mismo nombre de propiedad en c#?



utilice la palabra new para crear una instancia de objeto c# (5)

Las listas lo complican ... mi respuesta anterior (a continuación) solo se aplica a las propiedades semejantes (no a las listas). Sospecho que solo deberías escribir y mantener el código:

Student foo = new Student { Id = 1, Name = "a", Courses = { new Course { Key = 2}, new Course { Key = 3}, } }; StudentDTO dto = new StudentDTO { Id = foo.Id, Name = foo.Name, }; foreach (var course in foo.Courses) { dto.Courses.Add(new CourseDTO { Key = course.Key }); }

editar; solo se aplica a copias superficiales , no a listas

La reflexión es una opción, pero lenta. En 3.5 puedes construir esto en un código compilado con Expression . Jon Skeet tiene una muestra pre-laminada de esto en MiscUtil , solo use como:

Student source = ... StudentDTO item = PropertyCopy<StudentDTO>.CopyFrom(student);

Debido a que utiliza una Expression compilada, superará ampliamente la reflexión.

Si no tiene 3.5, use reflection o ComponentModel. Si usa ComponentModel, al menos puede usar HyperDescriptor para obtenerlo casi tan rápido como Expression

Student source = ... StudentDTO item = new StudentDTO(); PropertyDescriptorCollection sourceProps = TypeDescriptor.GetProperties(student), destProps = TypeDescriptor.GetProperties(item), foreach(PropertyDescriptor prop in sourceProps) { PropertyDescriptor destProp = destProps[prop.Name]; if(destProp != null) destProp.SetValue(item, prop.GetValue(student)); }

Supongamos que tengo dos clases:

public class Student { public int Id {get; set;} public string Name {get; set;} public IList<Course> Courses{ get; set;} } public class StudentDTO { public int Id {get; set;} public string Name {get; set;} public IList<CourseDTO> Courses{ get; set;} }

Me gustaría copiar el valor de la clase Student a la clase StudentDTO:

var student = new Student(); StudentDTO studentDTO = student;

¿Cómo puedo hacer eso por reflexión u otra solución?


Escribir un operador implícito en cualquier clase

public static implicit operator StudentDTO(Student student) { //use skeet''s library return PropertyCopy<StudentDTO>.CopyFrom(student); }

ahora puedes hacer eso

StudentDTO studentDTO = student;


Hay una biblioteca para hacer precisamente eso: http://emitmapper.codeplex.com/

Es mucho más rápido que AutoMapper, usa System.Reflection.Emit, por lo que el código se ejecuta casi tan rápido como si estuviera escrito a mano.


Ok, solo busqué el Misceláneo que Marc publicó y es simplemente increíble. Espero que a Mark no le importe agregar el código aquí.

using System; using System.Collections; using System.Collections.Specialized; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.ComponentModel; using System.Linq.Expressions; namespace ConsoleApplication1 { class Program { public class Student { public int Id { get; set; } public string Name { get; set; } public IList<int> Courses { get; set; } public static implicit operator Student(StudentDTO studentDTO) { return PropertyCopy<Student>.CopyFrom(studentDTO); } } public class StudentDTO { public int Id { get; set; } public string Name { get; set; } public IList<int> Courses { get; set; } public static implicit operator StudentDTO(Student student) { return PropertyCopy<StudentDTO>.CopyFrom(student); } } static void Main(string[] args) { Student _student = new Student(); _student.Id = 1; _student.Name = "Timmmmmmmmaaaahhhh"; _student.Courses = new List<int>(); _student.Courses.Add(101); _student.Courses.Add(121); StudentDTO itemT = _student; Console.WriteLine(itemT.Id); Console.WriteLine(itemT.Name); Console.WriteLine(itemT.Courses.Count); } } // COOLEST PIECE OF CODE FROM - http://www.yoda.arachsys.com/csharp/miscutil/ /// <summary> /// Generic class which copies to its target type from a source /// type specified in the Copy method. The types are specified /// separately to take advantage of type inference on generic /// method arguments. /// </summary> public class PropertyCopy<TTarget> where TTarget : class, new() { /// <summary> /// Copies all readable properties from the source to a new instance /// of TTarget. /// </summary> public static TTarget CopyFrom<TSource>(TSource source) where TSource : class { return PropertyCopier<TSource>.Copy(source); } /// <summary> /// Static class to efficiently store the compiled delegate which can /// do the copying. We need a bit of work to ensure that exceptions are /// appropriately propagated, as the exception is generated at type initialization /// time, but we wish it to be thrown as an ArgumentException. /// </summary> private static class PropertyCopier<TSource> where TSource : class { private static readonly Func<TSource, TTarget> copier; private static readonly Exception initializationException; internal static TTarget Copy(TSource source) { if (initializationException != null) { throw initializationException; } if (source == null) { throw new ArgumentNullException("source"); } return copier(source); } static PropertyCopier() { try { copier = BuildCopier(); initializationException = null; } catch (Exception e) { copier = null; initializationException = e; } } private static Func<TSource, TTarget> BuildCopier() { ParameterExpression sourceParameter = Expression.Parameter(typeof(TSource), "source"); var bindings = new List<MemberBinding>(); foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties()) { if (!sourceProperty.CanRead) { continue; } PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name); if (targetProperty == null) { throw new ArgumentException("Property " + sourceProperty.Name + " is not present and accessible in " + typeof(TTarget).FullName); } if (!targetProperty.CanWrite) { throw new ArgumentException("Property " + sourceProperty.Name + " is not writable in " + typeof(TTarget).FullName); } if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType)) { throw new ArgumentException("Property " + sourceProperty.Name + " has an incompatible type in " + typeof(TTarget).FullName); } bindings.Add(Expression.Bind(targetProperty, Expression.Property(sourceParameter, sourceProperty))); } Expression initializer = Expression.MemberInit(Expression.New(typeof(TTarget)), bindings); return Expression.Lambda<Func<TSource,TTarget>>(initializer, sourceParameter).Compile(); } } } }


FYI

Cuando estaba teniendo la misma pregunta, encontré AutoMapper ( http://automapper.codeplex.com/ ) Luego, después de leer la respuesta de AboutDev, hice una prueba simple, los resultados fueron bastante impresionantes.

aquí los resultados de la prueba:

Test Auto Mapper: 22322 ms

Operador implícito de prueba: 310 ms

Copia de propiedad de prueba: 250 ms

Test Emit Mapper: 281 ms

Y me gustaría subrayar que es solo una muestra con clases (StudentDTO, Student) que tienen solo un par de propiedades, pero lo que sucedería si las clases tuvieran de 50 a 100 propiedades, supongo que afectará el rendimiento dramáticamente.

Más detalles de las pruebas aquí: enfoques de copia de objeto en .net: Auto Mapper, Emit Mapper, Operación implícita, Property Copy