Pola abstract static

0

Chcę sobie napisać klasę abstrakcyjną, po której dziedziczyć będą wszystkie klasy reprezentujące tabele w bazie. Chcę, żeby każda klasa reprezentująca miała:
public static List<T> GetListOfItems()
public static List<T> GetItem(int id)
np:

class User : DBClass<Users>
{}

...

void function()
{
   User u = User.GetItem(1);
   List<User> list = User.GetListOfItems();
}

napisałem takie coś:

public abstract class DBClass<T> where T : class
    {
        public static List<T> GetListOfItems()
        {
            List<T> list = new List<T>();

            DBParser db = new DBParser();
            db.Command.CommandText = **select command1**
            DataSet ds = new DataSet();
            db.DataAdapter.Fill(ds);
            if (ds.Tables.Count == 1)
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    list.Add(**method 1(DataRow dr)**);
                }
            }

            return list;
        }

        protected static T GetItem(int id)
        {
            DBParser db = new DBParser();
            db.Command.CommandText = **select command 2**
            db.Command.Parameters.Add(new System.Data.SqlClient.SqlParameter("ID", id));
            DataSet ds = new DataSet();
            db.DataAdapter.Fill(ds);
            T obj = null;
            if(ds.Tables.Count == 1 && ds.Tables[0].Rows.Count == 1)
                obj = **method 1(DataRow dr**
            return obj;
        } 

Jedyne, czym różniłyby się te metody w każdej z klas T to(oprócz typu) select command 1 i 2.
Za method 1(DataRow dr można by dać

new T(DataRow dr)

, gdyby jakoś można było zadeklarować, że klasa zawsze ma taki konstruktor. Mogłoby to być też T.GetItem(DataRow dr)

, ale nijak nie wiem jak to (i czy w ogóle da się)zapisać.
Chciałbym mieć 2 pola static const w każdej z klas T(a właściwie chciałbym żeby ich implementacja była wymuszona) dla select command 1 i 2.
0

Wszystko wskazuje na to że się nie da bezpośrednio.
Żeby działało niestety trzeba udostępnić publiczny konstruktor bez parametrów dla klas T:

public class DBParser
    {
        public SqlConnection Connection { get; set; }
        public SqlCommand Command { get; set; }
        public SqlDataAdapter DataAdapter { get; set; }
        public SqlTransaction Transaction { get; set; }

        public DBParser()
        {
            System.Configuration.Configuration rootWebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/");
            Connection = new SqlConnection(rootWebConfig.ConnectionStrings.ConnectionStrings["DBString"].ConnectionString);
            Command = new SqlCommand();
            DataAdapter = new SqlDataAdapter();
            Command.Connection = Connection;
            DataAdapter.SelectCommand = Command;

        }
    }
public abstract class DBClass<T> where T : class, IDBInterface<T>, new()
    {
        public static List<T> GetListOfItems()
        {
            List<T> list = new List<T>();

            DBParser db = new DBParser();
            db.Command.CommandText = (new T()).ListCommandString;
            DataSet ds = new DataSet();
            db.DataAdapter.Fill(ds);
            if (ds.Tables.Count == 1)
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    list.Add((new T()).GetItem(dr));
                }
            }

            return list;
        }

        protected static T GetItem(int id)
        {
            DBParser db = new DBParser();
            db.Command.CommandText = (new T()).ItemCommandString;
            db.Command.Parameters.Add(new System.Data.SqlClient.SqlParameter("ID", id));
            DataSet ds = new DataSet();
            db.DataAdapter.Fill(ds);
            T obj = null;
            if(ds.Tables.Count == 1 && ds.Tables[0].Rows.Count == 1)
                obj = (new T()).GetItem(ds.Tables[0].Rows[0]);
            return obj;
        }

    } 
    public interface IDBInterface<T> where T : class
    {
        string ListCommandString { get; }
        string ItemCommandString { get; }

        T GetItem(DataRow dr);
    } 
    public class User: DBClass<User>, IDBInterface<User>
    {
        private const string getList = "SELECT * FROM dbo.USERS";
        private const string getItem = "SELECT * FROM dbo.USERS WHERE ID_USERA = @ID";

        public int ID_USERA { get; private set; }
        public string NAZWA_USERA { get; set; }
        public int ID_GRUPY { get; set; }
        
        public User()
        { }

        public User(string nazwa) : this()
        {
            NAZWA_USERA = nazwa;
        }

        public User(string nazwa, int idGrupy) : this(nazwa)
        {
            ID_GRUPY = idGrupy;
        }
        
        public string ListCommandString
        {
            get { return getList; }
        }

        public string ItemCommandString
        {
            get { return getItem; }
        }

        public Kategoria GetItem(DataRow dr)
        {
            User k = new User();

            if (dr.Table.Columns.Contains("ID_USERA"))
            {    
                  k.ID_USERA = (int)dr["ID_USERA"];
                  if (dr.Table.Columns.Contains("NAZWA_USERA"))
                      k.NAZWA_USERA = dr["NAZWA_USERA"].ToString();
                  if (dr.Table.Columns.Contains("ID_GRUPY"))
                      k.ID_GRUPY= (int)dr["ID_GRUPY"];
                  return k;
            }
            else
                return null;
        }
    } 
0
new T(DataRow dr)

To jest niemożliwe, chyba że użyjesz klasy Activator

Po pierwsze zrobiłeś ładnie klasę abstrakcyjną, ale nie widać w niej żadnej abstrakcji. To znaczy - twoje metody już istnieją, więc żadna klasa, która po niej dziedziczy nie nadpisze (nie powinna nadpisać!) tych dwóch metod.

Po drugie - zostaw te DataRow, DataTable itd w spokoju - tutaj o wiele lepiej wyjdzie użycie normalnego SqlCommand oraz SqlDataReader.

0

moja skromna wiedza n/t C# podpowiada mi, że metody statyczne nie są dziedziczone, a to oznacza, że nie mogą być abstrakcyjne. interfejsem też tego nie załatwisz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1