C#将类类型保存为预处理器
Posted
技术标签:
【中文标题】C#将类类型保存为预处理器【英文标题】:C# save class type as preprocessor 【发布时间】:2020-03-09 12:22:02 【问题描述】:在 C# 中是否可以像在 C/C++ 中一样将类类型保存为预处理器指令?
我有多个共享代码的服务。主要区别在于调用正确的DbSet
和使用正确的类。
从以下代码到:
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();
Ofc 上面的设计存在问题。当我尝试调用TaxService
时,我必须通过泛型类型传递Tax
类=> TaxService<Tax>
同样在GetAllAsync
方法中,我必须使用OfType
方法来避免编译器错误。不可能将List<Tax>
作为List<T>
返回
对设计模式有什么建议吗?谢谢
编辑(对 M. B. 的回答):
public class TaxService : TaxService<Tax>
public TaxService(DatabaseContext database) : base(database)
public class TaxService<T> where T : Tax
【问题讨论】:
存储库模式,结合“工作单元”可以解决它。 @MortenBork 感谢您的想法。我研究了一下,如果每个类(T)对于 DeleteAsync 方法都有相同的属性(名称),它对我有用。有时它的标题,有时它的名称.. 我想避免使用反射 嗨。请看一下我作为答案提供的示例...通过添加“表达式”作为谓词,您可以在控制器中定义要删除的内容。 【参考方案1】:我曾经构建过这样的基本控制器。
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>
然后只是创建一个实例。这样,您就拥有了一个控制器或存储库,以便在必须“关闭”某些事情时创建您的重载或独特的方法。
public void dostuff()
TaxController taxController = new TaxController();
taxController.Insert(item, context);
这在处理数据库时非常有用,它是由醉酒的程序员匆忙构建的,因为遵循相同模式的所有内容都可以使用,而所有不遵循相同模式的内容仍然可以通过控制器使用,无论数据库中存在什么异常,控制器都会负责“乱搞”。
这只是一个 PoC,您不必像这样精确地做。只是为了让你的吵闹。
【讨论】:
看起来不错。但是我想到了像 C++ 中的 #define T Tax 之类的东西。在谷歌上进行研究后,它在 C# 中是不可能的:/ 好吧,您可以在 where 添加一个条件,即您只接受“Tax”类作为 T,或者所有 T 必须属于 Tax 类。喜欢:公共类 TaxController以上是关于C#将类类型保存为预处理器的主要内容,如果未能解决你的问题,请参考以下文章