Recently, a DDD Project was implemented. Between the Domain Model and the Entity Model between the Domain layer and the persistence layer, sometimes attributes need to be copied. Although these attributes are different in their class names, however, their attribute names and types are almost the same. Many such models in the system need to be converted to each other. Some friends recommended using AutoMapper. It was good to try it and solve the problem. But as an old bird, I decided to study the implementation principle, so I also came to the shanzhai. In order to make this "Wheel" practical as possible, efficiency must be considered, so we decided to adopt the "Reflection + cache + delegation" path. For the first use, you must reflect the object attributes. This is simple. The following code is used: Type targetType ;//.... propertyInfo [] targetProperties = targetType. getProperties (BindingFlags. public | BindingFlags. instance); only attributes of Public Instance objects are obtained here. To copy attributes of the same name and Type, you need to find these attributes. The complete code is as follows: public ModuleCast (Type sourceType, Type targetType) {PropertyInfo [] targetProperties = targetType. getProperties (BindingFlags. public | BindingFlags. instance); foreach (PropertyInfo sp in sourceType. getProperties (BindingFlags. public | BindingFlags. instance) {foreach (PropertyInfo tp in targetProperties) {if (sp. name = tp. name & sp. propertyType = tp. propert YType) {CastProperty cp = new CastProperty (); cp. sourceProperty = new PropertyAccessorHandler (sp); cp. targetProperty = new PropertyAccessorHandler (tp); mProperties. add (cp); break ;}}} here a CastProperty class is used to save the source and target objects to be processed, in addition, this set of objects is cached in the mProperties static object in the CastProperty list. The following is the definition of the CastProperty class: // <summary> // convert the property object // </summary> public class CastProperty {public PropertyAccessorHandler SourceProperty {get; set ;} the public PropertyAccessorHandler TargetProperty {get; set ;}} class itself is very simple. The key is the property accesser PropertyAccessorHandler object, which is defined below: /// <summary> /// attribute accesser /// </summary> public class PropertyAccessorHandler {public PropertyAccessorHandler (PropertyInfo propInfo ){ This. propertyName = propInfo. name; // var obj = Activator. createInstance (classType); // var getterType = typeof (FastPropertyAccessor. getPropertyValue <> ). makeGenericType (propInfo. propertyType); // var setterType = typeof (FastPropertyAccessor. setPropertyValue <> ). makeGenericType (propInfo. propertyType); // this. getter = Delegate. createDelegate (getterType, null, propInfo. getGetMethod (); // this. setter = De Legate. createDelegate (setterType, null, propInfo. getSetMethod (); if (propInfo. canRead) this. getter = propInfo. getValue; if (propInfo. canWrite) this. setter = propInfo. setValue;} public string PropertyName {get; set;} public Func <object, object [], object> Getter {get; private set;} public Action <object, object, object []> Setter {get; private set ;}}when writing this class, I had made several detours and was prepared to use Delegate in the early stage. createD The elegate method creates a Delegate for the Get and Set methods of the current attribute. However, after several tests, it is found that Delegate. createDelegate (getterType, obj, propInfo. getGetMethod (); The obj here is either an object instance or null. If it is null, the delegate definition can only be bound to static attribute methods of the type. If it is not null, then this delegate can only be bound to the current obj instance object. In other words, if you use another obj-type instance object in the future, this delegate will still access the previous obj object, it is irrelevant to the new object instance. PS: In order to take this "detour", a FastPropertyAccessor was specially written a few days ago, declaring two generic delegates to bind the Get and Set methods of attributes, that is, the two lines of code commented out above: var getterType = typeof (FastPropertyAccessor. getPropertyValue <> ). makeGenericType (propInfo. propertyType); var setterType = typeof (FastPropertyAccessor. setPropertyValue <> ). makeGenericType (propInfo. propertyType); it is difficult to create this generic delegate, and the compilation is successful, but it is found that it cannot be used in the end, not to mention how depressing it is:-"regression topic, with PropertyAccessorHandler, then, we only need to traverse the attribute set of the target type to be converted, and then we can start Copied: public void Cast (object source, object target) {if (source = null) throw new ArgumentNullException ("source"); if (target = null) throw new ArgumentNullException ("target"); for (int I = 0; I <mProperties. count; I ++) {CastProperty cp = mProperties [I]; if (cp. sourceProperty. getter! = Null) {object Value = cp. SourceProperty. Getter (source, null); // PropertyInfo. GetValue (source, null); if (cp. TargetProperty. Setter! = Null) cp. targetProperty. setter (target, Value, null); // PropertyInfo. setValue (target, Value, null) ;}} the above Code will judge whether the Set accessors of the attribute are available, and copy the Value only when the Set accessors are available, therefore, the problem of "Read-Only attributes" can be solved. Note: The attribute value is copied directly here. The reference type is also a copy of the attribute reference, so this is a "superficial copy ". Now, the main code is available, because we cache the delegation of the access method for the properties of the execution type object, so our "property value Copy Program" has a high efficiency, in the previous article titled using generic delegation to build the fastest universal property accessors http://www.cnblogs.com/bluedoctor/archive/2012/12/18/2823325.html We have done a test. You can check the test results and cache the delegate method, which is very efficient. In order to make the applet easier to use, I wrote another extension method, make it easy for objects of the Object type to copy property values /// <summary> /// Object conversion extension /// </summary> public static class ModuleCastExtension {// <summary> // copy the attribute value of the current object to the target object, use superficial copy /// </summary> /// <typeparam name = "T"> target object type </typeparam> /// <param name = "source"> source object </param> /// <param name = "target"> target object, if it is null, A </param> // <returns> copied target object </returns> public static T CopyTo <T> (this object source, T targe T = null) where T: class, new () {if (source = null) throw new ArgumentNullException ("source"); if (target = null) target = new T (); ModuleCast. getCast (source. getType (), typeof (T )). cast (source, target); return target;} in this way, the applet can be used in several different forms as follows: // The following usage is the same: ModuleCast. getCast (typeof (CarInfo), typeof (ImplCarInfo )). cast (info, ic); ModuleCast. castObject <CarInfo, ImplCarInfo> (info, ic); ModuleCas T. castObject (info, ic); ImplCarInfo icResult = info. copyTo <ImplCarInfo> (null); ImplCarInfo icResult2 = new ImplCarInfo (); info. copyTo <ImplCarInfo> (icResult2); for the complete code download, see here. Supplement: Some attributes that cannot be copied need to be added after being used by netizens. I have simply rewritten the original code (the code is not included in the download above ): /// <summary> /// convert the attribute value of the source type to the attribute of the target type with the same name. /// </summary> /// <param name = "source"> </param> // <param name = "target"> </param> public void Cast (object source, object target) {Cast (source, target, null) ;}/// <summary >/// convert the attribute value of the source type to the attribute with the same name as the target type, exclude the attribute names to be filtered out /// </summary> /// <param name = "source"> </param> /// <param name = "target"> </param> /// <Param name = "filter"> name of the attribute to be filtered </param> public void Cast (object source, object target, string [] filter) {if (source = null) throw new ArgumentNullException ("source"); if (target = null) throw new ArgumentNullException ("target"); for (int I = 0; I <mProperties. count; I ++) {CastProperty cp = mProperties [I]; if (cp. sourceProperty. getter! = Null) {object Value = cp. SourceProperty. Getter (source, null); // PropertyInfo. GetValue (source, null); if (cp. TargetProperty. Setter! = Null) {if (filter = null) cp. TargetProperty. Setter (target, Value, null); else if (! Filter. contains (cp. targetProperty. propertyName) cp. targetProperty. setter (target, Value, null) ;}}} then modify the extension method: public static T CopyTo <T> (this object source, T target = null, string [] filter = null) where T: class, new () {if (source = null) throw new ArgumentNullException ("source"); if (target = null) target = new T (); ModuleCast. getCast (source. getType (), typeof (T )). cast (source, target, filter); return target;} Finally, call class Program {static void Main (string [] args) {A a = new () {Name = "aaa", NoCopyName = "no. no. no. "}; var B =. copyTo <B> (filter: new string [] {"NoCopyName"}) ;}www.2cto.com} class A {public string Name {get; set;} public string NoCopyName {get; set;} public DateTime GetTime {get {return DateTime. now ;}} class B {public string Name {get; set;} public string NoCopyName {get; set;} public DateTime GetTime {get {return DateTime. now ;}}}