您可以使用返回基类对象的数据访问方法填充派生类对象吗?

时间:2016-01-05 09:12:57

标签: c# inheritance casting

我想创建一个实现一些新方法的继承对象。基类只是一个数据容器,使用数据访问类填充。

我正在尝试使用强制框架,因此我更改这些基类的选项非常有限。

由于继承的对象具有与基础相同的所有数据字段和访问器,因此我希望使用基本数据访问类(及其方法)来填充派生类对象。我遇到的问题是DA层返回Base类型的填充对象。

实际上我正在尝试复制这些字段。我知道我可以创建一个接受基础对象并有效地逐字段复制的构造函数,但这是基础表性质的维护噩梦。

有没有办法在不重新编码DA层的情况下使演员“坚持”?

我认为唯一的方法是创建一个派生的数据访问类,它将处理派生的Base类,但是有更好的方法吗?

伪代码如下。该示例可能看起来微不足道,但DA层封装了大量数据检查和异常处理,因此很难在不破坏大量现有功能的情况下以任何有意义的方式进行修改。

我希望它有意义,因为很多代码都被删除了。

基类

public class oBase 
{
    #region "Constants"
    public const String FIELD_META_ID = "META_ID";
    public const String FIELD_MASTER_REF = "MASTER_REF";
    #endregion

    //Private Properties
    private Int32 m_iMetaID = 0;
    private String m_sMasterReference = "";
    //End Private Properties

    //Public Properties
    public Int32 MetaID { get { return m_iMetaID; } set { m_iMetaID = value; } }
    public String MasterReference { get { return m_sMasterReference; } set { m_sMasterReference = value; } }
    //End Public Properties
}

public class oBaseList
{
    private Int32 iMemberCount = 0;
    private List<oBase> m_BaseList = new List<oBase>();

    public Int32 Count
    {
        get { return m_BaseList.Count; }
    }

    public List<oBase> Items
    {
        get { return m_BaseList; }
    }

    public Boolean AddItem(oBase)
    {
        iMemberCount += 1;
        m_BaseList.Add(oBase);
        return true;
    }

}

扩展课程

class oBaseExtended : oBase
{
    public oBaseExtended(int iMetaID)
    {
        ConnectionManagerSQL oSqlConn = new ConnectionManagerSQL();
        daBase MyConnectedData = new daBase(ref oSqlConn);

        oBase MyCastData = new oBaseExtended();
        MyCastData = MyConnectedData.GetData(iMetaID);
        oBaseExtended MyRealData = (oBaseExtended)MyCastData;
        return MyRealData;
    }

}

数据访问

public class daBase
{

    private ConnectionManagerSQL oConn;

    public daBase(ref ConnectionManagerSQL sqlConn)
    {
        oConn = sqlConn;
    }

    #region "Gets"

    public oBase GetBase(Int32 iMetaID)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(" SELECT  ");
        sb.Append(" META_ID, ");
        sb.Append(" MASTER_REF, ");

        sb.Append(" from myTable ");
        sb.Append(" where META_ID = @META_ID");

        SqlCommand comm = new SqlCommand(sb.ToString(), oConn.DatabaseConnection);
        comm.Parameters.Add("META_ID", System.Data.SqlDbType.Int).Value = iMetaID;
        SqlDataReader drMyTableData = comm.ExecuteReader();

        return PopulateMyTableData(ref drMyTableData).Items[0];
    }
    #endregion

    #region "List population "

    private oBaseList PopulateMyTableData(ref SqlDataReader drMyTableData)
    {
        oBaseList ocdMyTableData = new oBaseList();
        oBase ocd;
        ocd = new oBase();

        ocd.MetaID = drMyTableData[oBase.FIELD_META_ID] is System.DBNull ? 0 : (Int32)drMyTableData[oBase.FIELD_META_ID];
        ocd.MasterReference = drMyTableData[oBase.FIELD_MASTER_REF] is System.DBNull ? "N/A" : (String)drMyTableData[oBase.FIELD_MASTER_REF];

        ocdMyTableData.AddItem(ocd);
        drMyTableData.Dispose();
        return ocdMyTableData;
    }

    #endregion

}

道歉,如果不清楚,并且有任何伪代码错误 - 我有点像C#新手。

我已更新代码以更好地反映真实的底层代码。

最好将问题放在:我可以一次性使用强制转换和复制到继承类型......

2 个答案:

答案 0 :(得分:1)

您可以使用反射将属性值和同名字段从一个对象复制到另一个对象。 检查https://msdn.microsoft.com/en-us/library/system.type%28v=vs.110%29.aspx 感兴趣的方法是GetPropertiesGetFields。 然后在PropertyInfoFieldInfo中,感兴趣的方法是GetValueSetValue

您可以编写一种复制属性/字段的方法,并为每个基础/派生对重用它。或者任何其他对象,只要属性和相同名称的字段是可分配的(即,不能将字符串分配给int等)。

编辑: 此方法复制属性值:

static void CopyData(object source, object destination)
{
  Type srcType = source.GetType();
  List<PropertyInfo> destProperties = new List<PropertyInfo>(destination.GetType().GetProperties());
  foreach (PropertyInfo destProperty in destProperties)
  {
    if (destProperty.CanWrite)
    {
      PropertyInfo srcProperty = srcType.GetProperty(destProperty.Name);
      if (srcProperty != null && srcProperty.CanRead)
      {
        destProperty.SetValue(destination, srcProperty.GetValue(source));
      }
    }
  }
}

如果您需要,请尝试添加字段复制,这是相同的原则。

答案 1 :(得分:0)

您可以通过基类构造函数填充派生类/基类共享的成员,如果需要,您还可以在派生类中填充任何扩展成员:

public class oBase
{
    private Int32 m_i = 0;
    private String m_s = "";
    public Int32 MI { get { return m_i; } set { m_i = value; } }
    public String MS { get { return m_s; } set { m_s = value; } }

    public oBase() { }

    public oBase(int i)
    {
        // populate base class members using instance of data access class
    }
}

您的派生类会扩展基础构造函数以填充任何扩展属性(我认为您没有?):

public class oBaseExtended : oBase
{
    public string foo { get; set; }
    public string bar { get; set; }

    public oBaseExtended() { }

    public oBaseExtended(int i) : base(i)
    {
        // this will invoke base class contructor to populate base members

        // then populate extended members afterwards if applicable
    }
}