当定义一类函数时,如何避免代码重复,这些函数只会改变它们处理的参数的数据类型



我有一个程序,它使用SQLite.SQLiteAsyncConnection执行数据库操作。我有两种不同的型号想要使用,比如客户和汽车。客户可以定义为

public class Customer
{
[PrimaryKey]
public string Id {get; set;}
public string Name {get; set;}
public int NumberOfKids {get; set;}
public decimal Budget {get; set;}
}

汽车可以定义为

public class Car
{
[PrimaryKey]
public string Id {get; set;}
public int Year {get; set;}
public string Make {get; set;}
public string Model {get; set;}
public int Mileage {get; set;}
}

请注意,这两个模型有不同数量和类型的成员,但都使用字符串Id作为主键。数据库操作是在我从公共接口IDataStore继承的一个类中定义的,该接口声明了添加、更新、删除和获取项的操作:

public interface IDataStore<T>
{
Task<bool> AddItemAsync(T item);
Task<bool> UpdateItemAsync(T item);
Task<bool> DeleteItemAsync(T item);
Task<T> GetItemAsync(string id);
Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false);
}

我是否必须为Cars和Customers定义一个单独的DataStore类或单独的重载函数,即使这两个模型的操作完全相同,除了它们作为参数使用的数据类型之外?我想申报的是类似的东西

public class SQLiteItemDataStore : IDataStore<var>
{
...
public async Task<var> GetItemAsync(string Id)
{
return await DrinkDatabase.Table<var>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
...
}

但这当然会产生编译器错误,因为您只能使用";var";在变量声明中,所以我必须为Cars 创建一个类

public class SQLiteItemDataStore : IDataStore<Car>
{
...
public async Task<Car> GetItemAsync(string Id)
{
return await DrinkDatabase.Table<Car>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
...
}

另一个为客户

public class SQLiteItemDataStore : IDataStore<Customer>
{
...
public async Task<Customer> GetItemAsync(string Id)
{
return await DrinkDatabase.Table<Customer>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
...
}

有没有一些标准的方法可以避免对我想与数据库一起使用的每个模型类型重复数据库操作函数?

我认为您正在寻找以下解决方案:

public interface IDataStore
{
Task<bool> AddItemAsync<T>(T item);
Task<bool> UpdateItemAsync<T>(T item);
Task<bool> DeleteItemAsync<T>(T item);
Task<T> GetItemAsync(string id);
Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false);
}
public class SQLiteDataStore
{
...
public async Task<T> GetItemAsync<T>(string Id)
{
return await DrinkDatabase.Table<T>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
...
}

但这不是常用的方法,而且它不起作用,因为你不知道t有Id属性。

试试这个:

  • 您应该定义一个基本实体类,并让所有模型从中继承

    public abstract class Entity {
    public abstract string Id {get;set;}
    }
    public class Car : Entity 
    {
    //all others cars properties
    }
    public class Customer : Entity 
    {
    //all others customers properties
    }
    
  • 您应该定义一个通用的通用存储库接口(就像您对IDataStore<T>所做的那样(

    public interface IRepository<T> where T : Entity // T must inherit from Entity
    {
    //all the methods you defined in IDataStore<T>
    }
    
  • 创建一个实现IRepository 所有方法的抽象类

    public abstract class RepositoryBase<T> : IRepository<T> where T : Entity
    {
    //all the methods of IRepository<T> are implemented in this class
    //now you don't have problems when calling t.Id if t is of type T because compiler knows that T derives from Entity
    }
    
  • 为您的实体创建特定的接口

    public interface ICarRepository : IRepository<Car>
    {
    //add car specific methods, i.e. IQueryable<Car> GetCarByCustomer(string customerId);
    }
    public interface ICustomerRepository : IRepository<Customer>
    {
    //add customer specific methods, i.e. Task<Customer> GetCustomerByCar(string carId);
    }
    
  • 创建具体类

    public class CarRepository : RepositoryBase<Car>, ICarRepository
    {
    //here you have to implement only car specific methods, i.e. IQueryable<Car> GetCarByCustomer(string customerId);
    }
    

这是最常用的方法,也称为存储库模式

相关内容

  • 没有找到相关文章

最新更新