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,您不必完全按照这个来做。只是为了引起你的注意 运行.