2011-09-06 8 views
1

수십 개의 도메인 객체 (사용자, 그룹, 역할, 커뮤니티, 포스트 등)가 있습니다. 또한 확장 된 개체 (UserExt, GroupExt 등)에서 파생 된 및 일부 추가 데이터가 포함되어 있습니다. 내 데이터 액세스 제어 레이어에는 기본 객체를 검색하는 메소드가 있습니다. 자식 개체에 데이터를 채울 필요가있을 때 이러한 메서드를 사용하지만 그 결과를 자식 형식으로 변환해야 할 때마다
부모 개체를 자식으로 캐스팅 할 수 없기 때문에 모든 부모 - 자식 쌍에 대한 변환기를 제공해야합니다 (생성자, 메서드, 기존 변환기 확장 또는 다른 방법을 통해). 그게 내가 내 변환기를 조정하는 것을 잊을 수있는 기본 유형에 어떤 필드를 추가하는 것처럼 내가 좋아하지 않는 것이다. 부모로부터 자녀의 입력란을 채우기위한 자동화 된 방법이 있습니까?
감사합니다.부모를 자식으로 변환

PS : 코드 :

도메인 오브젝트 :

public class Role : OutdoorObject 
{ 
    public String Name { get; set; } 
    public Int32 CreatedById { get; set; } 
    public Int32 UpdatedById { get; set; } 
} 

public class RoleExt : Role 
{ 
    public IPrincipal CreatedBy { get; set; } 
    public IPrincipal UpdatedBy { get; set; } 
} 

데이터 액세스 레이어 :

public Role GetById(Int32 roleId) 
{ 
    try 
    { 
     // seek in cache, return if found 
     LQ_Role lqRole = context.LQ_Roles.FirstOrDefault(r => r.RoleID == roleId); 
     Role result = LQMapper.LQToObject(lqRole); 
     // put result to cache 
     return result; 
    } 
    catch (Exception ex) 
    { 
     if (ex is BaseRepositoryException) throw ex; 
     else throw new UnknownRepositoryException(ex.Message); 
    } 
} 

서비스 층 :

public Role GetById(IPrincipal Executer, int roleID) 
    { 
     try 
     { 
      // perform operation 
      Role r = _repo.GetById(roleID); 

      // check access 
      if (!CanRead(Executer, r)) throw new OperationIsNotPermittedServiceException(); 

      return r; 
     } 
     catch (Exception ex) 
     { 
      // ... 
     } 
    } 

public RoleExt GetExtById(IPrincipal Executer, int roleID) 
{ 
    try 
    { 
     // perform operation 
     Role r = GetById(IPrincipal Executer, int roleID); 
     RoleExt result = new RoleExt(); 
     // here i need to convert r to result 
     // and populate addition fields 
     result.CreatedBy = userService.GetById(Executer, r.CreatedById); 
     result.UpdatedBy = userService.GetById(Executer, r.UpdatedById); 

     // check access 
     if (!CanRead(Executer, result)) throw new OperationIsNotPermittedServiceException(); 

     return result; 
    } 
    catch (Exception ex) 
    { 
     //... 
    } 
} 
+5

수행하려는 작업의 코드 예를 게시 할 수 있습니까? –

+0

@Chris, 업데이트 된 게시물 – Jim

답변

5

사용 반사,이 모든 복사합니다 공공 재산 f

public static void CopyOver(Parent p, Child c) 
    { 
     PropertyInfo[] props = p.GetType().GetProperties(BindingFlags.Public); 

     foreach(PropertyInfo pi in props) 
     { 
     pi.SetValue(c, pi.GetValue(p)); 
     } 
    } 
0
In my data access control layer there are methods for retrieving base objects 

을 취득합니다UserGroup는, Role는, Community는, Post 데이터 유형은 다음 다른 방법이없는 데이터 모델이 작동하고 경우 "수동으로"구현 : 아이의 부모가 롬 기본 객체와 대상 파생 클래스 사이의 "변환".

가 할 수있는 많은 방법이 있습니다 :

  • 특별한 변환 방법
  • 오버라이드 (override) 캐스트 oprators을
  • 객체 매퍼는

더 ...

0

그냥 움직임을 프레임 워크 Parent 객체로 변환합니다. 이를 통해 부모 당 하나의 변환을 작성하고 속성 변경을 단일 소스 파일에 유지할 수 있습니다. 확장 방법 위의 예에

public class Parent 
{ 
    public int Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public DateTime Prop3 { get; set; } 

    public T ToChild<T>() where T : Parent, new() 
    { 
     T child = new T(); 
     child.Prop1 = this.Prop1; 
     child.Prop2 = this.Prop2; 
     child.Prop3 = this.Prop3; 
     return child; 
    } 
} 
+1

네, 전환을 구현하는 방법은 여러 가지가 있지만 부모 개체 인 자식 개체에 더하여 일부 추가 기능을 더 암시 적으로 채울 수없는 이유는 분명하지 않습니다 ... 어쨌든 고마워요! – Jim

+0

@David B는 부모 클래스에서 자식 클래스로 User-> Client-> Supplier 클래스가있는 경우이 클래스가 적절한 솔루션 일 것입니다. 각 클래스는 부모 클래스에 대한 추가 속성 만 가질 수 있습니다. 따라서이 개체를 " 검색된 값에 따라 클래스를 변경하십시오. 사용자는 (이메일, 비밀번호) 고객이 (이름, 성, 전화 번호, 국가) 및 공급자가 클라이언트 속성 (회사 이름, 서비스 유형 ...)을 추가 할 때 추가합니다. –

+1

@ FernandoSilva 그것은 다음과 같은 두 가지 원칙을 명심해야합니다. 1) 학부모는 아동 학급에 대한 지식을 최소화해야합니다. 2) 각 클래스는 자체 속성을 관리해야합니다. –

1

작은 비틀기 ...

/// <summary> 
    /// Performs a shallow convert from the parent to the child object. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <typeparam name="U"></typeparam> 
    /// <param name="parent">The parent.</param> 
    /// <param name="child">The child.</param> 
    public static void ShallowConvert<T, U>(this T parent, U child) 
    { 
     foreach (PropertyInfo property in parent.GetType().GetProperties()) 
     { 
      if (property.CanWrite) 
      { 
       property.SetValue(child, property.GetValue(parent, null), null); 
      } 
     } 
    } 
0

AutoMapper 엔티티로 변환하는 가장 좋은 방법입니다. 확실히 시도해보십시오.

오토매 퍼를 사용하고 싶지 않다면 Btw는 @thumbmunkeys 코드를 확장했습니다.

/// <summary> 
/// Encapsulates useful functions to map domain objects with presentation objects. 
/// </summary> 
public static class Mapper 
{ 
    /// <summary> 
    /// Converts an object of <typeparamref name="U"/> to an object of <typeparamref name="T"/>. 
    /// </summary> 
    /// <typeparam name="U"></typeparam> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="instanceOfU"></param> 
    /// <returns></returns> 
    public static T Convert<U, T>(U instanceOfU) 
     where T : class, new() 
     where U : class, new() 
    { 
     T instanceOfT = new T(); 

     PropertyInfo[] tPropertyInfos = typeof(T).GetProperties(); 
     PropertyInfo[] uPropertyInfos = typeof(U).GetProperties(); 

     foreach (PropertyInfo tPropertyInfo in tPropertyInfos) 
     { 
      foreach (var uPropertyInfo in uPropertyInfos.Where(p => p.Name == tPropertyInfo.Name)) 
      { 
       if (tPropertyInfo.PropertyType == uPropertyInfo.PropertyType 
        && tPropertyInfo.SetMethod != null) 
       { 
        tPropertyInfo.SetValue(instanceOfT, uPropertyInfo.GetValue(instanceOfU)); 
       } 
      } 
     } 

     return instanceOfT; 
    } 

    /// <summary> 
    /// Converts an instance of type <typeparamref name="TChaild"/> to an instance of its parent type: <typeparamref name="TParent"/>. 
    /// </summary> 
    /// <typeparam name="TChild"></typeparam> 
    /// <typeparam name="TParent"></typeparam> 
    /// <param name="child"></param> 
    /// <returns></returns> 
    public static TParent ConvertChildToParent<TChild, TParent>(TChild child) 
     where TParent : class, new() 
     where TChild : class, new() 
    { 
     if (!typeof(TChild).IsDerivedFrom(typeof(TParent))) 
     { 
      throw new ArgumentException(string.Format("{0} is not derived from {1}.", typeof(TChild), typeof(TParent)), "TChild"); 
     } 

     return Convert<TChild, TParent>(child); 
    } 

    /// <summary> 
    /// Check if this type is derived from <typeparamref name="parentType"/>. 
    /// </summary> 
    /// <param name="thisType"></param> 
    /// <param name="parentType"></param> 
    /// <returns></returns> 
    public static bool IsDerivedFrom(this Type thisType, Type parentType) 
    { 
     Type derivedType = thisType; 

     do 
     { 
      derivedType = derivedType.BaseType; 

      if (derivedType != null) 
      { 
       if (derivedType == parentType) { return true; } 
      } 
     } while (derivedType != null); 

     return false; 
    } 
} 
관련 문제