将父母转换为孩子

问题描述:

我有几十个域对象(用户,组,角色,社区,帖子等)。另外我得到了扩展对象(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

使用反射,这将复制所有公共财产f ROM父到子:

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)); 
     } 
    } 

In my data access control layer there are methods for retrieving base objects 

如果您的数据模型,你操作和retriveUserGroupRoleCommunityPost数据类型,有则没有其他办法 “手动” 实施基础对象和目标派生类之间的“翻译”。

有很多方法可以做到这一点:

  • 特殊的转换方法
  • 被覆盖的铸造oprators
  • 对象映射构架

更多...

正义之举转换为父对象。这使您可以为每个父级编写一个转换,并将属性更改保留为单个源文件。

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这将是一个合适的解决方案,如果我有以下类用户 - >客户 - >供应商,从父母到孩子,其中每个孩子类只会有其他父母的属性,我想使对象“根据检索的值更改“类。用户将(电子邮件,密码)客户添加到(名称,姓氏,电话,国家),供应商将添加到客户的属性(公司名称,服务类型...)。 –

+1

@FernandoSilva它可能是...要记住的两个原则是:1)家长应尽量减少对儿童课程的了解。 2)每个班级都应该管理自己的房产。 –

小的调整,以上面的例子来扩展方法...

/// <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); 
      } 
     } 
    } 

AutoMapper是转换实体的最佳方式。绝对尝试。

顺便说一句,我扩展@thumbmunkeys的代码,如果你不想使用Automapper。

/// <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; 
    } 
}