2014-12-04 17 views
0

我想實現抽象工廠模式以最大化代碼效率來讀取我的coımmon引用類型。要做到這一點,我有以下實現抽象工廠執行錯誤

enter image description here

,並執行我已經實現了模式如下:

enter image description here

我對RefEntityFactor類代碼:

public class RefEntityFactory<T> : IRefEntityFactory<T> where T : IRefEntity 
{ 
    public List<T> Search(string sp_name, int? id, string code, int? statusid) 
    { 
     List<T> irefs = new List<T>(); 
     string procName = sp_name; 
     SqlConnection conn = null; 

     using (conn = GetConnection()) 
     { 
      SqlCommand cmd = new SqlCommand(procName, conn); 
      cmd.CommandType = CommandType.StoredProcedure; 

      if (id.HasValue) 
       cmd.Parameters.AddWithValue("@ID", id.Value); 
      if (!string.IsNullOrEmpty(code) && !string.IsNullOrWhiteSpace(code)) 
       cmd.Parameters.AddWithValue("@CODE", code.Trim()); 
      if (statusid.HasValue) 
       cmd.Parameters.AddWithValue("@STATUS", statusid.Value); 

      SqlDataReader rd = cmd.ExecuteReader(); 
      while (rd.Read()) 
      { 
       RefEntity refe = new RefEntity(); 
       refe.Id = int.Parse(rd["ID"].ToString()); 
       refe.Code = rd["CODE"].ToString(); 
       refe.Status = short.Parse(rd["STATUS"].ToString()); 
       IRefEntity iref = (IRefEntity)refe; 

       irefs.Add((T)iref); // Exception will be THROWN HERE!!!! 
      } 
      rd.Close(); 
     } 
     return irefs; 
    } 
} 

然後,我實現一個類spesific類型:

enter image description here

public static List<IPaymentType> SearchPaymentTypes(int? id, string code, int? statusid) 
    { 
     RefEntityFactory<IPaymentType> fact = new RefEntityFactory<IPaymentType>(); 

     return fact.Search(@"[dbo].[SEARCH_PAYMENTTYPES]", id, code, statusid); 
    } 

但很明顯,當我運行它拋出在哪裏標記爲註釋的行異常的代碼。

如何更正我的實施?

問候。

+0

不應該你的方法返回'List '而不是'List ',你的代碼試圖將'RefEntity'強制轉換爲'T',所以如果'T'比'RefEntity'多派生,那麼它會失敗。你也可以做'IRefEntity iref = new RefEntity();'並完全移除'refe'。 – 2014-12-04 13:34:49

+0

是零異常還是文件未找到異常? – 2014-12-04 13:36:04

+0

@BenRobinson:當我將返回類型轉換爲列表而不是列表時,我無法編寫SearchPaymentTypes方法。返回類型將是我需要返回IPaymentType和list.ForEach(x =>(IPaymentType)x)集合的IRefEntity的集合;不管用。 – user3021830 2014-12-04 13:45:43

回答

1

最終,這將是因爲RefEntityT型的沒有,你試圖通過構建新的T採用的方法,所以像這樣在你的while循環:

T refe = new T(); 
refe.Id = int.Parse(rd["ID"].ToString()); 
refe.Code = rd["CODE"].ToString(); 
refe.Status = short.Parse(rd["STATUS"].ToString()); 

irefs.Add(ref); 

你也需要擴展generic constraint限制你T要求參數的構造函數一樣,所以是這樣的:

public class RefEntityFactory<T> : IRefEntityFactory<T> where T : IRefEntity, new() 

還你應該改變個SearchPaymentTypes如下,使其工作:

public static List<IPaymentType> SearchPaymentTypes(int? id, string code, int? statusid) 
    { 
     RefEntityFactory<PaymentType> fact = new RefEntityFactory<PaymentType>(); 
     List<PaymentType> list = fact.Search(@"[dbo].[SEARCH_PAYMENTTYPES]", id, code, description, statusid); 

     return list.Select(x => (IPaymentType)x).ToList(); 
    } 
+0

當我進行更改時,建議出現以下錯誤: *'Interfaces.IPaymentType'必須是具有公共無參數構造函數的非抽象類型,才能將其用作泛型類型或方法中的參數'T' ** SearchPaymentTypes **方法中的'RefEntityFactory '*。 – user3021830 2014-12-04 13:48:13

0

的問題是RefEntityFactory創建RefEntity對象。 RefEntitys不能轉換爲IPaymentType,因爲它們不實現IPaymentType。

您不需要使用通用參數來實現抽象工廠模式。抽象工廠的方法可以返回IRefEntity:

interface IRefEntityFactory 
{ 
    List<IRefEntity> Search(string sp_name, int? id, string code, int? statusid); 
} 

和混凝土工廠將返回實現IRefEntity各種具體的實體類型:

class PayrollEntityFactory : IRefEntityFactory 
{ 
    public List<IRefEntity> Search(string sp_name, int? id, string code, int? statusid) 
    { 
     List<IRefEntity> ret = new List<IRefEntity>(); 
     ret.Add(new PaymentType()); 
     return ret; 
    } 
} 

class NnnnEntityFactory : IRefEntityFactory 
{ 
    public List<IRefEntity> Search(string sp_name, int? id, string code, int? statusid) 
    { 
     List<IRefEntity> ret = new List<IRefEntity>(); 
     ret.Add(new NnnnType()); 
     return ret; 
    } 
} 

或者抽象工廠可能是一個抽象類而不是一個接口。這將允許所有實現共享通用代碼,並避免重複SQL查詢等大部分操作。但實際的具體對象(例如工資)創建不能共享,每個對象的構造都需要是唯一的。