如何以IDataModel为参数并访问具体模型类的属性?
如何通过IDataModel参数访问具体模型类的独有属性?
问题描述
我正在设计一款读写SQL Server数据库的应用,拥有多个对应表记录的模型类。定义了IDataModel接口供这些模型实现,同时定义了包含Update方法签名的IDataStoreUpdatable接口,方法参数为IDataModel。但在实现Update方法时,无法访问模型的独有属性(这些属性未在IDataModel中定义),尝试强制转换为具体类也无效。想请教是否有办法以IDataModel为参数,同时访问实际类的属性?
相关代码:
internal interface IDataModel { int ID { get; set; } } internal interface IDataStoreUpdatable { void Update(IDataModel model); void Update(List<IDataModel> models); } public void Update(IDataModel bom) { transaction = new CommittableTransaction(); string updateString = $@"UPDATE tblBOMs SET lngPalletSectionID = {bom.PalletSection.ID}, lngQuoteID = {bom.QuoteID}, strComponent = '{bom.Component}', bytQuantityNeeded = {bom.QuantityNeeded}, sngBDFT = {bom.BoardFeet} WHERE lngBOMID = {bom.ID}"; OpenConnection(); _sqlConnection.EnlistTransaction(transaction); // .... }
解决方案
方案一:使用泛型接口约束(推荐)
将IDataStoreUpdatable改成泛型接口,通过泛型约束限定为IDataModel的实现类,这样Update方法可以直接接收具体模型类型,无需转换就能访问独有属性,同时保证类型安全。
示例代码:
// 定义泛型更新接口,约束T为IDataModel的实现类 internal interface IDataStoreUpdatable<T> where T : IDataModel { void Update(T model); void Update(List<T> models); } // 针对具体模型类(比如BOMModel)实现接口 public class BOMDataStore : IDataStoreUpdatable<BOMModel> { public void Update(BOMModel bom) { transaction = new CommittableTransaction(); // 直接访问BOMModel的所有属性 string updateString = $@"UPDATE tblBOMs SET lngPalletSectionID = {bom.PalletSection.ID}, lngQuoteID = {bom.QuoteID}, strComponent = '{bom.Component}', bytQuantityNeeded = {bom.QuantityNeeded}, sngBDFT = {bom.BoardFeet} WHERE lngBOMID = {bom.ID}"; OpenConnection(); _sqlConnection.EnlistTransaction(transaction); // .... } public void Update(List<BOMModel> models) { // 批量更新逻辑 } }
方案二:安全类型检查与转换(保留非泛型接口时使用)
如果必须保留原有的非泛型接口,可以在Update方法中先判断参数的实际类型,再进行安全转换,避免直接强制转换导致的运行时错误。
示例代码:
public void Update(IDataModel model) { // 用模式匹配安全转换为具体类 if (model is not BOMModel bom) { throw new ArgumentException("传入的模型不是BOMModel类型", nameof(model)); } transaction = new CommittableTransaction(); string updateString = $@"UPDATE tblBOMs SET lngPalletSectionID = {bom.PalletSection.ID}, lngQuoteID = {bom.QuoteID}, strComponent = '{bom.Component}', bytQuantityNeeded = {bom.QuantityNeeded}, sngBDFT = {bom.BoardFeet} WHERE lngBOMID = {bom.ID}"; OpenConnection(); _sqlConnection.EnlistTransaction(transaction); // .... }
额外提醒:避免SQL注入风险
你的代码中直接拼接SQL字符串存在严重的SQL注入风险,建议改用参数化查询:
string updateString = @"UPDATE tblBOMs SET lngPalletSectionID = @PalletSectionID, lngQuoteID = @QuoteID, strComponent = @Component, bytQuantityNeeded = @QuantityNeeded, sngBDFT = @BoardFeet WHERE lngBOMID = @ID"; using var command = new SqlCommand(updateString, _sqlConnection); command.Parameters.AddWithValue("@PalletSectionID", bom.PalletSection.ID); command.Parameters.AddWithValue("@QuoteID", bom.QuoteID); command.Parameters.AddWithValue("@Component", bom.Component); command.Parameters.AddWithValue("@QuantityNeeded", bom.QuantityNeeded); command.Parameters.AddWithValue("@BoardFeet", bom.BoardFeet); command.Parameters.AddWithValue("@ID", bom.ID); command.ExecuteNonQuery();
内容的提问来源于stack exchange,提问作者James Dorsey
相关产品推荐
相关产品推荐

