/// <summary> /// 관계 정보를 모두 불러와서 활성화 시키기. 지우기용. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <param name="seen"></param> public static void ActivateRelation4Cascade <T>(this T source, HashSet <object> seen) where T : IDbModel { if (source == null) { logger.Debug(string.Format("ActivateRelation Source is null : type={0}", typeof(T).FullName)); return; } if (seen.Contains(source) == true) { return; } else { seen.Add(source); } var props = source.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(CascadeRelationAttribute), true).Length != 0 || p.GetCustomAttributes(typeof(CascadeRelationAttribute)).Count() != 0); foreach (var prop in props) { CascadeRelationAttribute attr = (CascadeRelationAttribute)prop.GetCustomAttribute(typeof(CascadeRelationAttribute)); if (attr.Direction == CascadeRelationAttribute.CascadeDirection.Down) { if (typeof(IDbModel).IsAssignableFrom(prop.PropertyType)) { var t = prop.GetValue(source, null); ((IDbModel)t).ActivateRelation4Cascade(seen); } else if (typeof(ICollection <>).IsAssignableFrom(prop.PropertyType.GetGenericTypeDefinition())) { var t = (IEnumerable)prop.GetValue(source, null); if (t != null) { foreach (var item in t) { if (typeof(IDbModel).IsAssignableFrom(item.GetType())) { ((IDbModel)item).ActivateRelation4Cascade(seen); } else { logger.Debug(string.Format("ActivateRelation Property ICollection<T> T not IDbModel type={0}, ToString={1}", item.GetType().FullName, item.GetType().ToString())); } } } } else { logger.Debug(string.Format("ActivateRelation Property not IDbModel type={0}, ToString={1}", prop.PropertyType.FullName, prop.PropertyType.ToString())); } } } }
/// <summary> /// Deep 복사 본 만들기. DB 저장을 위해 관계 처리 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="source"></param> /// <param name="seen"></param> /// <param name="bCopykey"></param> /// <param name="bCascade"></param> /// <param name="direction"></param> /// <param name="bClone"></param> /// <returns></returns> public static TEntity Clone <TEntity>(this TEntity source, Dictionary <object, object> seen, bool bCopykey, bool bCascade, CascadeRelationAttribute.CascadeDirection direction, bool bClone) where TEntity : IKeyModel { if (source == null) { logger.Debug(string.Format("Clone Source is null return default(T): type={0}", typeof(TEntity).FullName)); return(default(TEntity)); } if (seen.ContainsKey(source) == true) { return((TEntity)seen[source]); } //부모자식 관계 일 때는 자식이 부모를 만들지 않고 원본을 그대로 돌려주도록 해야 함 if (direction == CascadeRelationAttribute.CascadeDirection.Up || bClone == false) { logger.Debug(string.Format("Clone Source as it is : type={0}, id={1}", source.GetType().FullName, source.ToString())); seen.Add(source, source); return(source); } TEntity clone = (TEntity)Activator.CreateInstance(source.GetType()); seen.Add(source, clone); //NonCopyable 하지 않고, CascadeRelation에 속하지 않은 프로퍼티 모두 복사 var props = source.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(NonCopyableAttribute), true).Length == 0 && p.GetCustomAttributes(typeof(NonCopyableAttribute)).Count() == 0 && p.GetCustomAttributes(typeof(CascadeRelationAttribute), true).Length == 0 && p.GetCustomAttributes(typeof(CascadeRelationAttribute)).Count() == 0); var keyName = source.GetKeyName(); //Key의 이름은 동적으로 받아서 사용. foreach (var prop in props) { if (prop.Name == keyName) { if (bCopykey == false) { continue; } } prop.SetValue(clone, prop.GetValue(source, null), null); } //CascadeRelation에 속한 프로퍼티는 Cascade 복사 if (bCascade == true) { props = source.GetType().GetProperties().Where(p => (p.GetCustomAttributes(typeof(CascadeRelationAttribute), true).Length != 0 || p.GetCustomAttributes(typeof(CascadeRelationAttribute)).Count() != 0) && p.GetCustomAttributes(typeof(NonCopyableAttribute), true).Length == 0 && p.GetCustomAttributes(typeof(NonCopyableAttribute)).Count() == 0); foreach (var prop in props) { if (typeof(IKeyModel).IsAssignableFrom(prop.PropertyType)) { var t = (IKeyModel)prop.GetValue(source, null); CascadeRelationAttribute attr = (CascadeRelationAttribute)prop.GetCustomAttribute(typeof(CascadeRelationAttribute)); prop.SetValue(clone, t == null ? null : t.Clone(seen, bCopykey, bCascade, attr.Direction, attr.Clonable), null); } else if (prop.PropertyType.IsGenericType && typeof(ICollection <>).IsAssignableFrom(prop.PropertyType.GetGenericTypeDefinition())) { var listType = typeof(List <>); var constructedListType = listType.MakeGenericType(prop.PropertyType.GetGenericArguments()[0]); var instance = (IList)Activator.CreateInstance(constructedListType); var t = (IEnumerable)prop.GetValue(source, null); if (t != null) { foreach (var item in t) { if (typeof(IKeyModel).IsAssignableFrom(item.GetType())) { CascadeRelationAttribute attr = (CascadeRelationAttribute)prop.GetCustomAttribute(typeof(CascadeRelationAttribute)); instance.Add(item == null ? null : ((IKeyModel)item).Clone(seen, bCopykey, bCascade, attr.Direction, attr.Clonable)); } else { logger.Debug(string.Format("Clone Property ICollection<T> T not IKeyModel type={0}, ToString={1}", item.GetType().FullName, item.GetType().ToString())); } } } prop.SetValue(clone, instance, null); } else { logger.Debug(string.Format("Clone Property not IKeyModel type={0}, ToString={1}", prop.PropertyType.FullName, prop.PropertyType.ToString())); } } } return(clone); }