2009-03-02 58 views
2

我一直在试图创建一个简单的基类来封装我的数据库访问的一些约定。我通常会创建一个名为“products_retrieve_product”的存储区,以根据productID选择一个产品。我希望基类中的“Retrieve”方法返回派生类在其定义中提供的类型。我正试图用泛型来实现吗?如何通过基类中的方法返回泛型?

public class MyBaseClass <T> 
{ 
    private string _className; 

    public MyBaseClass() 
    { 
     _className = this.GetType().Name; 
    } 

    public virtual T Retrieve(int ID) 
    { 
     Database db = DatabaseFactory.CreateDatabase(); 
     DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", _className)); 
     db.AddInParameter(dbCommand, String.Format("@{0}ID", _className), DbType.Int32, ID); 

     using (IDataReader dr = db.ExecuteReader(dbCommand)) 
     { 
      if (dr.Read()) 
      { 
       BOLoader.LoadDataToProps(this, dr); 
      } 
     } 
     return (T)this; 
    } 
} 

回答

2

我认为,你想要做这样的事情:

class MyBaseClass<T> where T : MyBaseClass<T>, new() 
{ 
    public T Retrieve() 
    { 
     return new T(); 
    } 
} 

class Foo : MyBaseClass<Foo> 
{ 
} 

class Program 
{ 
    public static void Main() 
    { 
     Foo f = new Foo(); 
     Foo f2 = f.Retrieve(); 
     Console.WriteLine(f2.ToString()); 
    } 
} 

当你运行该程序,Foo的类型名称将打印在命令行中。显然这是一个人为的例子,但是也许你可以在MyBaseClass.Retrieve()从数据库加载时做更有用的事情。

关键是在T上添加一个约束,以便它必须是类本身的一个实例。这种方式可以指定子类作为子类的通用类型MyBaseClass<T>.

我不完全确定这是否是一个好主意,但它看起来可以完成。

-1

不,它不是,因为你真正需要的是能够做的就是这样的类定义:

public class MyBaseClass<T> : T 

目前是不可能的仿制药。你需要做的是将工厂从工厂生产中分离出来(你需要一个单独的类来构建T,然后你应该提供帮助者方法来处理T,可能是扩展方法)。

1

当然。在您的例子,如果我想我的Foo类检索时返回酒吧(...)被调用:

public class Foo : MyBaseClass<Bar>{} 
+0

我卡上的部分是“检索”方法是如何铸就的对象为派生类型。 – 2009-03-02 19:37:24

0

嗯,我们使用反射来获取类名。 BOLoader无疑是使用反射来加载一些属性。为什么不完全致力于反思?

BOLoader不关心这个“返回类型”的游戏。我们为什么要?

public static class MyBaseClassExtender 
{ 
    public static void Retrieve(this MyBaseClass entity, int ID) 
    { 
     string className = entity.GetType().Name; 
     Database db = DatabaseFactory.CreateDatabase(); 
     DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", className)); 
     db.AddInParameter(dbCommand, String.Format("@{0}ID", className), DbType.Int32, ID); 

     using (IDataReader dr = db.ExecuteReader(dbCommand)) 
     { 
      if (dr.Read()) 
      { 
       BOLoader.LoadDataToProps(this, dr); 
      } 
     } 
    } 
} 

然后你只需要说:

Foo myFoo = new Foo(); 
myFoo.Retrieve(2);