简体   繁体   English

关于c#接口和泛型的问题

[英]A question regarding c# interfaces and maybe generics

We have built an internal tool that generates the whole data access, each table has a class the represents it's data and all the common operations.(think lightweight Entity framework). 我们构建了一个生成整个数据访问的内部工具,每个表都有一个表示它的数据和所有常见操作的类。(想想轻量级实体框架)。

These DataAccess objects always have a constructor that receives a connection string, and a Load function that receives a SqlDataReader. 这些DataAccess对象始终具有接收连接字符串的构造函数和接收SqlDataReader的Load函数。

Something like this: 像这样的东西:

class Customer
{
    public string ConnStr;
    public int Id;
    public string Name;

    Public customers(string connStr)
    {
        ConnStr = connStr;
    }

    public Customer Load(SqlDataReader)
    {
        if(reader.Read())
        {
            Id = reader["Id"].ToString();
            Name = reader["Name"].ToString();
        }   
    }
}

I want to write a utility Data Access static method that will allow me to write my SQL and get a list of objects in return, following that previous object example: 我想编写一个实用程序数据访问静态方法,它允许我编写我的SQL并获得一个返回的对象列表,遵循上一个对象示例:

string SQL = "SELECT * FROM Customers WHERE Name=@Name";
List<Customer> customers = GetList<Customer>(connStr, SQL, new SqlParameters("@Name", "John"));

I somehow can't figure how to deal with it, I have tried interfaces but they don't allow constructors or static methods, and using generics - i can't call the methods i need to init the object(constructor + load), here is my latest try, commented out the section that doesn't work: 我不知道如何处理它,我已经尝试过接口,但他们不允许构造函数或静态方法,并使用泛型 - 我不能调用我需要初始化对象的方法(构造函数+加载),这是我的最新尝试,注释掉了不起作用的部分:


public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
        {
            List<T> list = new List<T>();

            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();

                SqlCommand cmd = new SqlCommand(SQL, conn);
                foreach (SqlParameter param in prms)
                {
                    cmd.Parameters.Add(param);
                }

                using (SqlDataReader reader = cmd.ExecuteReader())
                {

                    //T item = new T(connStr);
                    //item.Load(reader);
                    //list.Add(item);
                }
            }

            return list;
        }

Btw, we are interested in open sourcing our DataAccess generator, it's amazing - it allow very effecient access to DB objects + creates a javascript data access layer that gives you FULL CONTROL of your DB from javascript(ofcourse this has security implications which can be managed). 顺便说一句,我们感兴趣的是开源我们的DataAccess生成器,它很棒 - 它允许非常有效地访问数据库对象+创建一个javascript数据访问层,让你可以从javascript完全控制你的数据库(当然这有安全隐患,可以管理)。

If anyone here knows how to "open source" a project like this or any company that wants to join the development of this product - please feel free contacting me: eytan@titkadem.co.il 如果有人知道如何“开源”这样的项目或任何想加入该产品开发的公司 - 请随时与我联系:eytan@titkadem.co.il

Thanks in advance, Eytan 提前谢谢,Eytan

The Load is easy enough - you could have: Load很简单 - 您可以:

interface IDataEntity {
    void Load(SqlDataReader reader);
}

then: 然后:

public static List<T> GetList<T>(string connStr, string SQL,
      params SqlParameter[] prms) where T : IDataEntity, new()
{
    .... 
    T item = new T();
    item.Load(reader);
    list.Add(item);
}

The new T(connStr) is trickier - does it really need this value? new T(connStr)比较棘手 - 它真的需要这个值吗? A public property would be easier : 公共财产会更容易

interface IDataEntity {
    void Load(SqlDataReader reader);
    string ConnectionString {get;set;}
}
class Customer : IDataEntity 
{ ... }

etc. There isn't any inbuilt (language) support for parameterised generic constructors. 等参数化通用构造函数没有任何内置(语言)支持。 You can hack around it, but in many cases the parameterised forms of Activator.CreateInstance are fast enough (when compared to data-access over a network, reflection is negligible). 您可以解决它,但在许多情况下, Activator.CreateInstance的参数化形式足够快(与通过网络进行数据访问相比,反射可以忽略不计)。 If you need a parameterised version it can be done with Expression etc (let me know if you want an example). 如果您需要参数化版本,可以使用Expression等完成(如果您想要一个示例,请告诉我)。

Why not passing constr to a method: 为什么不将constr传递给方法:

T item = new T();
item.SetConn(connStr);

And do not forget: 别忘了:

public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
  where T : new
{

You need to go to reflection, unless you want to change how your classes work in the way of constructors. 你需要去反思,除非你想改变你的类如何以构造函数的方式工作。

You can do this: 你可以这样做:

while (reader.Read())
{
    T item = Activator.CreateInstance(typeof(T), new object[] { connStr }) as T;
    item.Load(reader);
    list.Add(item);
}

(note here, I made it the responsibility of the above loop to call .Read on the reader) (注意这里,我让上面的循环负责调用。读取阅读器)

Note that unless you expose the Load method through an interface, you need to call that through reflection as well. 请注意,除非通过接口公开Load方法,否则还需要通过反射调用它。

I would do this: 我会这样做:

public interface IDataObject
{
    void Load(IDataReader reader);
}

And then implement this for your Customer: 然后为您的客户实施此操作:

public class Customer : IDataObject
{
    ...

And then add a constraint to your GetList method: 然后为GetList方法添加一个约束:

public List<T> GetList<T>(string connStr, string sql, params SqlParameter[] parameters)
    where T : IDataObject

This will not work as you wish. 这不会按你的意愿工作。 SQL classes for .net are not strongly typed. .net的SQL类不是强类型的。 It it impossible to say from query like SELECT * FROM Customers... object of what class has to be constructed. 它不可能从查询中说出像SELECT * FROM Customers...必须构造什么类的对象。 This is possible if all your entities derive from single class that declares: 如果所有实体派生自声明的单个类,则可以执行以下操作:

public virtual Entity Load(SqlDataReader reader)

and your generic method has constraint: 并且您的泛型方法有约束:

public static List<T> GetList<T>(string connStr, string SQL, params SqlParameter[] prms)
   where T : Entity, new()

then you could do: 然后你可以这样做:

T entity = new T();
entity.Load(reader);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM