2014-12-04 62 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查询等大部分操作。但实际的具体对象(例如工资)创建不能共享,每个对象的构造都需要是唯一的。