/// <summary>POCO型を、POCO型にマップ</summary> /// <typeparam name="TSource">srcのPOCO型</typeparam> /// <typeparam name="TDestination">dstのPOCO型</typeparam> /// <param name="src">srcのPOCOインスタンス</param> /// <param name="dst">dstのPOCOインスタンス(null可)</param> /// <param name="map">Dictionary(dst property or field string, src property or field string)</param> /// <returns>TDestination型のPOCO</returns> public static TDestination Map <TSource, TDestination>(TSource src, TDestination dst, Dictionary <string, string> map) { // POCOのnew() if (dst == null) { dst = InstanceCreator <TDestination> .Factory(); } AccessorCacher.CacheAccessor(dst); // dstの型 AccessorCacher.CacheAccessor(src); // srcの型 // dst foreach (AccessorInfo dst_ai in AccessorCacher.CncDic[dst.GetType()]) { string dstName = dst_ai.AccessorName; string srcName = ""; // マップの有無 if (map == null) { // マップ無 srcName = dstName; } else { // マップ有 if (map.ContainsKey(dstName)) { // 値あり srcName = map[dstName]; } else { // 値なし srcName = dstName; } } // src foreach (AccessorInfo src_ai in AccessorCacher.CncDic[src.GetType()]) { if (srcName == src_ai.AccessorName) { dst_ai.SetDelegate(dst, src_ai.GetDelegate(src)); } } } return(dst); }
/// <summary>DataReaderからPOCOに変換する。</summary> /// <typeparam name="T">POCOの型</typeparam> /// <param name="dr">IDataReader</param> /// <param name="map">Dictionary(poco property or field string, data field string)</param> /// <returns>T型のPOCO</returns> public static T DataReaderToPOCO <T>(IDataReader dr, Dictionary <string, string> map) { // drのDataTableスキーマ情報 .net coreで動かない。 //DataTable dt = dr.GetSchemaTable(); // https://stackoverflow.com/questions/373230/check-for-column-name-in-a-sqldatareader-object HashSet <string> hs = PubCmnFunction.GetDataReaderColumnInfo(dr); //PerformanceRecorder pr = new PerformanceRecorder(); //pr.StartsPerformanceRecord(); // POCOの型 T obj = default(T); //obj = Activator.CreateInstance<T>(); obj = InstanceCreator <T> .Factory(); AccessorCacher.CacheAccessor(obj); // IDataReader の既定の位置は、先頭のレコードの前 if (dr.Read()) { // POCOのnew() // InstanceCreator<T>.Factory()の性能測定の名残 //PerformanceRecorder pr = new PerformanceRecorder(); //pr.StartsPerformanceRecord(); //for (int i = 0; i < 1000; i++) //{ obj = InstanceCreator <T> .Factory(); //} //Debug.WriteLine(pr.EndsPerformanceRecord()); foreach (AccessorInfo ai_dst in AccessorCacher.CncDic[obj.GetType()]) { string srcName = ai_dst.AccessorName; // マップの有無 if (map == null) { // マップ無 } else { // マップ有 if (map.ContainsKey(srcName)) { // 値あり srcName = map[srcName]; } else { // 値なし } } if (hs.Contains(srcName)) { if (object.Equals(dr[srcName], DBNull.Value)) { // DBNullの場合、指定しない。 } else { // DBNullで無い場合、指定する(Nullable対応の型変換を追加)。 //prop.SetValue(obj, PubCmnFunction.ChangeType(dr[srcPropName], prop.PropertyType), null); //ai.Delegate(obj, PubCmnFunction.ChangeType(dr[srcName], ai.Type)); object srcValue = dr[srcName]; object dstValue = null; Type srcType = srcValue.GetType(); if (ai_dst.UnderlyingType == null) { // Nullableではない if (srcType == ai_dst.AccessorType) { // 型一致の場合は変換不要 dstValue = srcValue; } else { dstValue = Convert.ChangeType(srcValue, ai_dst.AccessorType); } } else { // Nullableである if (srcType == ai_dst.AccessorType) { // 型一致の場合は変換不要 dstValue = srcValue; } else { // Convert.ChangeTypeの性能測定の名残 //PerformanceRecorder pr = new PerformanceRecorder(); //pr.StartsPerformanceRecord(); //for (int i = 0; i < 1000; i++) //{ // Convert.ChangeType() doesn't handle nullables -> use UnderlyingType. dstValue = (srcValue == null ? null : Convert.ChangeType(srcValue, ai_dst.UnderlyingType)); //} //Debug.WriteLine(pr.EndsPerformanceRecord()); } } // AccessorInfo.SetDelegateの性能測定の名残 //PerformanceRecorder pr = new PerformanceRecorder(); //pr.StartsPerformanceRecord(); //for (int i = 0; i < 1000; i++) //{ ai_dst.SetDelegate(obj, dstValue); //} //Debug.WriteLine(pr.EndsPerformanceRecord()); } } } } //Debug.WriteLine(pr.EndsPerformanceRecord()); return(obj); }