2

我有 2 节课:

  • 员工
  • 员工详情

我有这样的Employee类方法:

public static Employee LoadEmployee(int id)
{
    StringBuilder selectQuery = new StringBuilder();

    string selectQuery = " my query with the parameter 'Id' ";
    dbGenerator _db = dbGenerator.Instance.Database;

    DbCommand selectCommand = _db.GetSqlStringCommand(selectQuery.ToString());
    _db.AddInParameter(selectCommand, "@id", System.Data.DbType.String, Id);

    //EXECUTE THE COMMAND
    using (IDataReader dr = _db.ExecuteReader(selectCommand))
    {
        if (dr.Read())
        {
            result = new Employee();
            Employee.LoadDataReader(result, dr);
        }

        dr.Close();
    }

    return result;
}

而且我有一个方法对EmployeeDetails类做同样的事情......除了返回类型之外没有任何变化。

我确信有一些方法可以最大限度地减少代码行,并且使用 C# 泛型它会更具可读性,并且泛型提供类型安全性,而不会产生多个实现的开销。

我需要一个可以传递类对象的方法selectQueryParameterId就像这样

public static <T> LoadData<T>(Object object, string selectQuery, int paramId)
{
    // do stuff 

    // return <T>results;
}

任何建议将不胜感激。

4

5 回答 5

1

最好的方法是使用某种 ORM(EntityFramework 或 NHibernate),因为这样您就可以免费获得通用管理。

但是,这样的事情可能会起作用:

public static T LoadEntity<T>(int id, StringBuilder selectQuery) where T : Entity
        {
            dbGenerator _db = dbGenerator.Instance.Database;
            DbCommand selectCommand = _db.GetSqlStringCommand(selectQuery.ToString());
            _db.AddInParameter(selectCommand, "@id", System.Data.DbType.String, Id);
            //EXECUTE THE COMMAND
            using (IDataReader dr = _db.ExecuteReader(selectCommand))
            {
                if (dr.Read())
                {
                    T result = default(T);
                    EntityContext.LoadDataReader(result, dr);
                }
                dr.Close();
            }
            return result;
        }

如您所见,此解决方案要求您继承EntityEntity包含方法LoadDataReader。此外,您必须传入查询。

免责声明:未经测试的代码!

于 2012-07-09T14:03:43.523 回答
1

拥有两者EmployeeEmployeeDetails 从同一接口继承,因此它们都具有 LoadDataReader 方法。

然后

public static T Load<T> (int id) 
    where T: IMyInterface

您可能需要在您的 LoadDataReader 方法中进行一些反思或一些花哨的事情。

于 2012-07-09T14:03:44.397 回答
1

EmployeeDataReader首先,为和提供一个共同点EmployeeDetailsDataReader

泛型在这里帮助提供不同的返回类型。因此,您需要一个基类(或接口)来处理它。例如,EmployeeDataReaderBase<TEmployee>

然后数据读取器可以从这个基类继承。

然后将您的方法更改为:

public static Employee LoadEmployee<TEmployee>(int id, EmployeeDataReaderBase<TEmployee> datareader)
于 2012-07-09T14:04:33.903 回答
1

您可以将“接口继承”与LoadDataReader作为接口方法一起使用(假设 LoadDataReader 对于 Employee 和 EmployeeDetails 是不同的)。然后将实例传递给静态 LoadEmployee 方法;将返回类型设置为 void

interface IDataReader
{
   void Load(DataReader reader);
}

public class Employee : IDataReader
{
   // some code... members...

   public void Load(DataReader reader)
   {
        /// some code...
   }
}

public static void Load(IDataReader reader, int id)
{
   // lots of code...
   if (dr.Read())
   {        
        // the specific reader would create its own type within... 
        // there by keeping the instance creation with in the LoadDataReader.
        // ex: If reader's type is Employee it would create Employee and setup the object with info from the reader?
        reader.LoadDataReader(dr);

   }
}
于 2012-07-09T14:08:33.510 回答
1

其他人关于只使用 ORM 的建议很好,但如果你有充分的理由从头开始做这个层,你可以修改你的设计看起来像这样:

public class Employee 
{
    public virtual void InitFromDataReader(DataReader dr) { }
}

public class EmployeeDetails : Employee
{
    public override void InitFromDataReader(DataReader dr) { }
}

public static TEmployee LoadEmployee<TEmployee>(int id) where TEmployee : Employee, new()
{
    using (DataReader dr = new DataReader()) 
    {
        var result = new TEmployee();
        result.InitFromDataReader(dr);
        return result;
    }
}

主要限制是您需要在实体对象上具有无参数构造函数,否则LoadEmployee方法无法正确创建它们。也就是说,除非您明确地将工厂对象作为参数传递给该方法。

于 2012-07-09T14:11:02.363 回答