2017-09-14 45 views
-1

如果標題的措辭不正確,請原諒我。如何在工廠返回T時訪問值列表<T>以及未知

我從各種設備的數據庫表中檢索數據並構建一個列表。不同的設備可能具有相同的屬性,並且肯定會有一些不同的屬性,所以我使用工廠模式在運行時創建需要的任何一個。

工廠類:

public interface IImportModel 
{ 
    IList CreateImportList(SqlDataReader reader); 
} 

和混凝土類:

public class Device1ImportModel : IImportModel 
{ 
    public string SerialNumber { get; set; } 
    public string PartA { get; set; } 

    public IList CreateImportList(SqlDataReader reader) 
    { 
     Device1ImportModel linkedItem = new Device1ImportModel(); 

     List<Device1ImportModel> importList = new List<Device1ImportModel>(); 

     while (reader.Read()) 
     { 
      linkedItem = new Device1ImportModel(); 

      linkedItem.SerialNumber = reader["SerialNo"].ToString(); 
      linkedItem.PartA = reader["PartA"].ToString(); 

      importList.Add(linkedItem); 
     } 

     return importList; 
    } 
} 

我從工廠創建設備:

importModel = ImportModelFactory.CreateImportModel("Device1"); 

現在,當我想遍歷importModel,我在嘗試訪問item.SerialNumber的行上收到編譯時錯誤。

foreach (var item in importList)     
{ 
     string number = item.SerialNumber; 
} 

錯誤:

'object' does not contain a definition for 'SerialNumber' and no extension method 'SerialNumber' accepting a first argument of type 'object' could be found.

如果我把一個斷點和項目變量懸停,我能看到的屬性和價值。

我嘗試使用動態而不是var,但後來在我的代碼中,我不能再使用Linq或Lambda查詢。

  1. 如何訪問這些值?
  2. 我可以使用反射將IList轉換爲List嗎?

編輯1

添加的代碼爲CreateImportModel:

static public IImportModel CreateImportModel(DeviceType device) 
{ 
    switch (device) 
    { 
     case DeviceType.Device1: 
      return new Device1ImportModel(); 

     case DeviceType.Device2: 
      return new DeviceImportModel(); 

     default: 
      return null; 
    } 
} 
+0

請包含'CreateImportModel'的源代碼。 – mjwills

+0

所有設備類型是否都有'SerialNumber'? – mjwills

回答

2

變化IListList<Device1ImportModel>(或IList<Device1ImportModel>IReadOnlyList<Device1ImportModel>)。

public List<Device1ImportModel> CreateImportList(SqlDataReader reader) 

IList是一個較舊的接口(預仿製藥),因此,如果您使用IList(而不是IList<Device1ImportModel),則編譯器/運行時沒有數據的Type的概念(即它把它作爲object),即:

'object' does not contain a definition for 'SerialNumber' and no extension method 'SerialNumber' accepting a first argument of type 'object' could be found.

您可能還需要改變接口:

public interface IImportModel<T> 
{ 
    List<T> CreateImportList(SqlDataReader reader); 
} 

和類:

public class Device1ImportModel : IImportModel<Device1ImportModel> 
{ 
    public string SerialNumber { get; set; } 
    public string PartA { get; set; } 

    public List<Device1ImportModel> CreateImportList(SqlDataReader reader) 
    { 

你可能也想更改CreateImportModel所以不要這麼說:

ImportModelFactory.CreateImportModel("Device1"); 

你,而不是把它想:

ImportModelFactory.CreateImportModel<Device1ImportModel>(); 

使混凝土Device1ImportModel返回(因而SerialNumber是訪問)。

+0

這不起作用,因爲我的接口設置爲IList CreateImportList(SqlDataReader reader);我有超過一個具體的類,並不會提前知道哪一個被稱爲... – Neill

+1

@Neill然後遍歷該列表,並期望它具有僅在一個具體類型中找到的屬性是設計缺陷。如果所有具體類型都有一個'SerialNumber',那麼將它作爲接口的一部分並使用'List '。 – Rotem

+0

更新是否有助於@Neill? – mjwills

3

如果你不能改變你的方法的簽名,你可以使用:

foreach (var item in importList.Cast<Device1ImportModel>())     
{ 
    string number = item.SerialNumber; 
} 

這將拋出一個異常,但是,如果會出現importList的集合,是不是Device1ImportModel或其派生類對象中的。

如果你不知道的是,在列表中的所有對象都是這種類型的,並希望避免異常,使用此apporach:

foreach (var item in importList.OfType<Device1ImportModel>())     
{ 
    string number = item.SerialNumber; 
} 
+0

我不知道哪個班級要打電話。 – Neill

+1

@Neill,如果你不知道哪個類會期望,你怎麼能確定會有'SerialNumber'屬性?那麼你的問題沒有解決方案。 – dymanoid

+0

有一些屬性,所有類將始終有。 SerialNumber就是其中之一。 – Neill

0

最後我只使用一個單獨的類來保存所有屬性,每個其他的具體課程是否使用它們。

它不理想,但工程。

我寧願依靠每個具體類來負責它自己的屬性。

相關問題