C# 将 class 类型保存为预处理器
C# save class type as preprocessor
在 C# 中是否可以像在 C/C++ 中那样将 class 类型保存为预处理器指令?
我有多个服务,其中有很多共享代码。主要区别在于调用正确的 DbSet
和使用正确的 class.
从以下代码到:
public class TaxService
{
readonly DatabaseContext db;
public TaxService(DatabaseContext database)
{
db = database;
}
public async Task<string> DeleteAsync(int? id)
{
if (await db.Taxes.FindAsync(id) is Tax tax)
{
string title = tax.Name;
db.Taxes.Remove(tax);
try
{
await db.SaveChangesAsync();
return title;
}
catch (Exception ex)
{
throw;
}
}
return null;
}
public async Task<List<Tax>> GetAllAsync()
{
return await db.Taxes.AsNoTracking().ToListAsync();
}
}
例如:
public class TaxService<T> where T : Tax
{
readonly DatabaseContext db;
DbSet<Tax> dbSet => db.Tax;
public TaxService(DatabaseContext database)
{
db = database;
}
public async Task<string> DeleteAsync(int? id)
{
if (await dbSet.FindAsync(id) is T tax)
{
string title = tax.Name;
dbSet.Remove(tax);
try
{
await db.SaveChangesAsync();
return title;
}
catch (Exception ex)
{
throw;
}
}
return null;
}
public async Task<List<T>> GetAllAsync()
{
return await dbSet.AsNoTracking().OfType<T>().ToListAsync();
}
}
当然上面的设计有问题。当我尝试调用 TaxService
时,我必须通过泛型类型传递 Tax
class => TaxService<Tax>
同样在方法 GetAllAsync
中,我必须使用 OfType
方法来避免编译器错误。它不可能 return List<Tax>
as List<T>
对设计模式有什么建议吗?谢谢
编辑(对 M. B. 的回答):
public class TaxService : TaxService<Tax>
{
public TaxService(DatabaseContext database) : base(database)
{
}
}
public class TaxService<T> where T : Tax
我曾经构建过这样一个基本控制器。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
namespace DataAccessLayer.Controllers
{
public class BaseController<TEntity> where TEntity : class, new()
{
public virtual TEntity Get<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().FirstOrDefault(predicate);
return item;
}
public List<TEntity> GetList<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().Where(predicate).ToList();
return item;
}
public IQueryable<TEntity> GetListQueryable<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().Where(predicate);
return item;
}
public List<TEntity> GetAll<TContext>(TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().ToList();
return item;
}
public IEnumerable<TEntity> GetAllEnumerable<TContext>(TContext context) where TContext : DbContext
{
IEnumerable<TEntity> item = context.Set<TEntity>();
return item;
}
public virtual TEntity Update<TContext>(TEntity input, Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
if (input == null)
return null;
var existing = context.Set<TEntity>().FirstOrDefault(predicate);
if (existing != null) context.Entry(existing).CurrentValues.SetValues(input);
return existing;
}
public virtual TEntity Insert<TContext>(TEntity input, TContext context) where TContext : DbContext
{
context.Set<TEntity>().Add(input);
return input;
}
}
}
您可以像这样创建一个控制器来使用它:
public class TaxcController : BaseController<Tax>
{
}
然后只是创建一个实例。这样,您就有了一个控制器或存储库,可以在 "off" 必须完成某些事情时创建您的重载或独特的方法。
public void dostuff()
{
TaxController taxController = new TaxController();
taxController.Insert(item, context);
}
这在处理数据库时非常有用,它是由醉酒的程序员匆忙构建的,因为所有遵循相同模式的东西都可以使用,而所有不遵循相同模式的东西仍然可以通过控制器,控制器只对 "screwing around" 负责,数据库中存在任何异常。
这只是一个PoC,您不必完全按照这个来做。只是为了引起你的注意 运行.
在 C# 中是否可以像在 C/C++ 中那样将 class 类型保存为预处理器指令?
我有多个服务,其中有很多共享代码。主要区别在于调用正确的 DbSet
和使用正确的 class.
从以下代码到:
public class TaxService
{
readonly DatabaseContext db;
public TaxService(DatabaseContext database)
{
db = database;
}
public async Task<string> DeleteAsync(int? id)
{
if (await db.Taxes.FindAsync(id) is Tax tax)
{
string title = tax.Name;
db.Taxes.Remove(tax);
try
{
await db.SaveChangesAsync();
return title;
}
catch (Exception ex)
{
throw;
}
}
return null;
}
public async Task<List<Tax>> GetAllAsync()
{
return await db.Taxes.AsNoTracking().ToListAsync();
}
}
例如:
public class TaxService<T> where T : Tax
{
readonly DatabaseContext db;
DbSet<Tax> dbSet => db.Tax;
public TaxService(DatabaseContext database)
{
db = database;
}
public async Task<string> DeleteAsync(int? id)
{
if (await dbSet.FindAsync(id) is T tax)
{
string title = tax.Name;
dbSet.Remove(tax);
try
{
await db.SaveChangesAsync();
return title;
}
catch (Exception ex)
{
throw;
}
}
return null;
}
public async Task<List<T>> GetAllAsync()
{
return await dbSet.AsNoTracking().OfType<T>().ToListAsync();
}
}
当然上面的设计有问题。当我尝试调用 TaxService
时,我必须通过泛型类型传递 Tax
class => TaxService<Tax>
同样在方法 GetAllAsync
中,我必须使用 OfType
方法来避免编译器错误。它不可能 return List<Tax>
as List<T>
对设计模式有什么建议吗?谢谢
编辑(对 M. B. 的回答):
public class TaxService : TaxService<Tax>
{
public TaxService(DatabaseContext database) : base(database)
{
}
}
public class TaxService<T> where T : Tax
我曾经构建过这样一个基本控制器。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
namespace DataAccessLayer.Controllers
{
public class BaseController<TEntity> where TEntity : class, new()
{
public virtual TEntity Get<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().FirstOrDefault(predicate);
return item;
}
public List<TEntity> GetList<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().Where(predicate).ToList();
return item;
}
public IQueryable<TEntity> GetListQueryable<TContext>(Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().Where(predicate);
return item;
}
public List<TEntity> GetAll<TContext>(TContext context) where TContext : DbContext
{
var item = context.Set<TEntity>().ToList();
return item;
}
public IEnumerable<TEntity> GetAllEnumerable<TContext>(TContext context) where TContext : DbContext
{
IEnumerable<TEntity> item = context.Set<TEntity>();
return item;
}
public virtual TEntity Update<TContext>(TEntity input, Expression<Func<TEntity, bool>> predicate, TContext context) where TContext : DbContext
{
if (input == null)
return null;
var existing = context.Set<TEntity>().FirstOrDefault(predicate);
if (existing != null) context.Entry(existing).CurrentValues.SetValues(input);
return existing;
}
public virtual TEntity Insert<TContext>(TEntity input, TContext context) where TContext : DbContext
{
context.Set<TEntity>().Add(input);
return input;
}
}
}
您可以像这样创建一个控制器来使用它:
public class TaxcController : BaseController<Tax>
{
}
然后只是创建一个实例。这样,您就有了一个控制器或存储库,可以在 "off" 必须完成某些事情时创建您的重载或独特的方法。
public void dostuff()
{
TaxController taxController = new TaxController();
taxController.Insert(item, context);
}
这在处理数据库时非常有用,它是由醉酒的程序员匆忙构建的,因为所有遵循相同模式的东西都可以使用,而所有不遵循相同模式的东西仍然可以通过控制器,控制器只对 "screwing around" 负责,数据库中存在任何异常。
这只是一个PoC,您不必完全按照这个来做。只是为了引起你的注意 运行.