С# - Как сделать следующий класс базовым классом, чтобы дочерние классы могли иметь те же свойства, методы?

62
3

Я создал следующий класс, который работает с конкретной таблицей базы данных. Как я могу сделать этот класс базовым классом, чтобы другие классы могли иметь одни и те же свойства и методы, но возвращать правильный тип, и единственное, что мне нужно сделать, это назначить правильное имя таблицы?

Спасибо заранее, я надеюсь, что мой вопрос ясен.

Вот класс:

public class AccountType
{
private static string tableName = "accountTypes";

private int id = -1;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}

private string name = "";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

private static List<AccountType> accountTypes = new List<AccountType> ();
public static List<AccountType> AccountTypes
{
get
{
return accountTypes;
}
}

public AccountType ()
{
}

public AccountType Clone ()
{
AccountType o = (AccountType)this.MemberwiseClone ();

return o;
}

public static AccountType Fill (DataRow row)
{
int id = Convert.ToInt32 (row["id"].ToString ());
string name = row["name"].ToString ();

AccountType o = new AccountType ();
o.id = id;
o.name = name;

return o;
}

public static List<AccountType> FillAll (DataRowCollection rows)
{
List<AccountType> objs = new List<AccountType> ();

foreach (DataRow row in rows)
{
AccountType o = Fill (row);

if (o != null)
objs.Add (o);
}

return objs;
}

public static List<AccountType> GetAll ()
{
if (AccountType.accountTypes.Count > 0)
return AccountType.accountTypes;

List<AccountType> objs = new List<AccountType> ();

string query = "SELECT * \r\n" +
"FROM " + AccountType.tableName + " \r\n" +
"WHERE id > -1 \r\n" +
"ORDER BY name";

DataSet result = Global.Db.ExecuteQuery (query);

if (
(result == null)
|| (result.Tables[0] == null)
|| (result.Tables[0].Rows.Count < 1)
)
{
return objs;
}

objs = FillAll (result.Tables[0].Rows);

return objs;
}

public static AccountType GetById (int id)
{
foreach (AccountType at in AccountType.accountTypes)
{
if (at.id == id)
return at;
}

AccountType o = null;

string query = "SELECT * \r\n" +
"FROM " + AccountType.tableName + " \r\n" +
"WHERE id = " + id + " \r\n";

DataSet result = Global.Db.ExecuteQuery (query);

if (
(result == null)
|| (result.Tables[0] == null)
|| (result.Tables[0].Rows.Count < 1)
)
{
return o;
}

o = Fill (result.Tables[0].Rows[0]);

return o;
}

public static void Load ()
{
AccountType.accountTypes = AccountType.GetAll ();
}

public void Save ()
{
string tn = AccountType.tableName;
string query = "INSERT INTO " + tn + " (name) " +
"VALUES ( @name)";

SQLiteCommand command = new SQLiteCommand ();
command.CommandText = query;
command.CommandType = CommandType.Text;

command.Parameters.Add (new SQLiteParameter("@currencyPair", this.name));

Common.Global.Db.ExecuteNonQuery (command);
}

public void Update ()
{
string query = "UPDATE " + AccountType.tableName + " \r\n" +
"SET name = @name \r\n" +
"WHERE id = @id";

SQLiteCommand command = new SQLiteCommand ();
command.CommandText = query;
command.CommandType = CommandType.Text;

command.Parameters.Add (new SQLiteParameter("@id", this.id));
command.Parameters.Add (new SQLiteParameter("@name", this.name));

Common.Global.Db.ExecuteNonQuery (command);
}
}

спросил(а) 2021-01-25T18:42:32+03:00 4 месяца, 4 недели назад
1
Решение
109

Я на 80% уверен, что понимаю, что вы сомневаетесь, поэтому, надеюсь, этот ответ поможет. Я думаю, что Curiously Recurring Template Pattern может помочь

Идея заключается в том, что вы это делаете (я только что реализовал случайные бит, чтобы, надеюсь, дать вам представление о том, что он может сделать для вас)

public abstract class BaseClass<T> where T : BaseClass<T>
{

public string Id {get; set;}
public string OtherProperty {get; set;}
public T WorkWithTAndReturn(T instanceOfASubClass)
{
//you can access base properties like
var theId = T.Id;
T.OtherProperty = "Look what I can do";
return T
}
public T Clone()
{
var newT = DoCloneStuff(instanceToClone);//do clone stuff here
return newT;
}

public static T Clone(T instanceToClone)
{
return (T)instanceToClone.MemberwiseClone();
}
}

Примечание: "BaseClass" является абстрактным, потому что вы не хотите создавать экземпляры этого экземпляра. Поскольку T должен быть подклассом BaseClass<T> вы создаете экземпляр подкласса, вы не делаете этого нового BaseClass, потому что это просто лишний и нечетный. Приведение его в абстракцию также позволяет вам при необходимости реализовать некоторые функции

Итак, вы создаете класс, который происходит из BaseClass<T>

public class MySubClass : BaseClass<MyClass>
{
//put what ever implementation you want in here
}

и это можно использовать

var mySubClass = new MySubClass();
SubClass clone = mySubClass.Clone();
SubClass otherClone = SubClass.Clone(mySubClass);

Изменение: Дополнительная информация

public static T Fill(DataRow row)
{
int id = Convert.ToInt32(row["id"].ToString());
string name = row["name"].ToString();
T o = new T();
o.id = id;
o.name = name;
return o;
}
public static List<T> FillAll(DataRowCollection rows)
{
List<T> objs = new List<T>();
foreach (DataRow row in rows)
{
T o = Fill(row);
if (o != null)
objs.Add(o);
}
return objs;
}

Эта модель решает некоторые проблемы, связанные с статическими функциями. Однако статические поля или свойства доступны только в классе, в котором они реализованы. Они не наследуются. Статическая строковая поддержка класса A не относится к классу B, даже если класс B наследует класс A.

Я думаю, что этот шаблон будет указывать вам в правильном направлении, но вам нужно будет пересмотреть свой шаблон несколько

Редактировать 2: ОК, так что моя идея обойти этот дорожный блок поля статического имени таблицы, который у вас есть

public abstract class TableDesciptor
{
public abstract string TableName { get; }
}

public class AccountType<T,U>
where T : AccountType<T,U>, new()
where U : TableDesciptor, new()
{
private static string tableName = new U().TableName;
public static List<T> AccountTypes
{
get
{
return accountTypes;
}
}

public int Id { get; set; }

public string Name { get; set; }

private static List<T> accountTypes = new List<T>();

public AccountType()
{
}

public T Clone()
{
T o = (T)this.MemberwiseClone();

return o;
}

public static T Fill(DataRow row)
{
int id = Convert.ToInt32(row["id"].ToString());
string name = row["name"].ToString();

T o = new T();
o.Id = id;
o.Name = name;

return o;
}

public static List<T> FillAll(DataRowCollection rows)
{
List<T> objs = new List<T>();

foreach (DataRow row in rows)
{
T o = Fill(row);

if (o != null)
objs.Add(o);
}

return objs;
}

public static List<T> GetAll()
{
if (accountTypes.Count > 0)
return accountTypes;

List<T> objs = new List<T>();

string query = "SELECT * \r\n" +
"FROM " + AccountType<T,U>.tableName + " \r\n" +
"WHERE id > -1 \r\n" +
"ORDER BY name";

DataSet result = Global.Db.ExecuteQuery(query);

if (
(result == null)
|| (result.Tables[0] == null)
|| (result.Tables[0].Rows.Count < 1)
)
{
return objs;
}

objs = FillAll(result.Tables[0].Rows);

return objs;
}

public static T GetById(int id)
{
foreach (T at in accountTypes)
{
if (at.Id== id)
return at;
}

T o = null;

string query = "SELECT * \r\n" +
"FROM " + AccountType<T,U>.tableName + " \r\n" +
"WHERE id = " + id + " \r\n";

DataSet result = Global.Db.ExecuteQuery(query);

if (
(result == null)
|| (result.Tables[0] == null)
|| (result.Tables[0].Rows.Count < 1)
)
{
return o;
}

o = Fill(result.Tables[0].Rows[0]);

return o;
}

public static void Load()
{
accountTypes = GetAll();
}

public void Save()
{
string tn = AccountType<T,U>.tableName;
string query = "INSERT INTO " + tn + " (name) " +
"VALUES ( @name)";

SQLiteCommand command = new SQLiteCommand();
command.CommandText = query;
command.CommandType = CommandType.Text;

command.Parameters.Add(new SQLiteParameter("@currencyPair", this.Name));

Common.Global.Db.ExecuteNonQuery(command);
}

public void Update()
{
string query = "UPDATE " + AccountType<T,U>.tableName + " \r\n" +
"SET name = @name \r\n" +
"WHERE id = @id";

SQLiteCommand command = new SQLiteCommand();
command.CommandText = query;
command.CommandType = CommandType.Text;

command.Parameters.Add(new SQLiteParameter("@id", this.Id));
command.Parameters.Add(new SQLiteParameter("@name", this.Name));

Common.Global.Db.ExecuteNonQuery(command);
}
}

ответил(а) 2021-01-25T18:42:32+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема