可以使用返回基类对象的数据访问方法来填充派生类对象吗
本文关键字:对象 填充 派生 方法 数据 返回 基类 可以使 访问 | 更新日期: 2023-09-27 18:28:57
我想创建一个继承的对象来实现一些新方法。基类只是一个数据容器,使用数据访问类填充。
我正在尝试使用一个强制框架,所以我更改这些基类的选项非常有限。
由于继承的对象具有与基本对象相同的所有数据字段和访问器,我希望使用基本数据访问类(及其方法)来填充派生类对象。我遇到的问题是,DA层返回一个类型为Base的填充对象。
实际上,我正在尝试复制字段。我知道我可以创建一个接受基本对象并有效地逐字段复制的构造函数,但这对底层表的性质来说是一场维护噩梦。
有没有办法在不重新编码DA层的情况下让演员阵容"粘"起来?
我相信实现这一点的唯一方法是创建一个派生的数据访问类,它将处理派生的基类,但有更好的方法吗?
伪代码如下。这个例子可能看起来微不足道,但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#新手。
我已经更新了代码,以便更好地反映真实的底层代码。
最好的问题是:我可以简单地一次性使用转换和复制到继承的类型吗。。。
您可以使用反射将相同名称的属性和字段的值从一个对象复制到另一个对象。检查https://msdn.microsoft.com/en-us/library/system.type%28v=vs.110%29.aspx感兴趣的方法是GetProperties
和GetFields
。然后在PropertyInfo
和FieldInfo
中,感兴趣的方法是GetValue
和SetValue
。
您可以编写一个复制属性/字段的方法,并将其用于每个基/派生对。或者任何其他对象对,只要相同名称的属性和字段是可赋值的(即不能将字符串分配给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));
}
}
}
}
如果您需要,也可以尝试添加字段复制,这是相同的原则。
您可以通过基类构造函数填充派生类/基类共享的成员,必要时还可以填充派生类中的任何扩展成员:
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
}
}