如何从T类型中获取T的类型?

时间:2017-02-21 18:01:42

标签: c# generics asp.net-core-mvc

我正在尝试将我的组织使用的框架重写为.Net Core;特别是此时的通用存储库。 我坚持以下问题。

我们的BaseEntity定义如下:

public abstract class BaseEntity<T> : IBaseEntity<T>
{
    [Key]
    public virtual T Id { get; set; }
}

它继承自Interface:

public interface IBaseEntity<T>
{
    [Key]
    T Id { get; set; }
}

我定义了一个这样的实体:

public class Employee : BaseEntity<int>
{
    public string OfficeBureau { get; set; }
    public string Supervisor { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Notes { get; set; }

    // TODO:
    // public virtual ICollection<Case> Cases { get; set; }
}

AppContext:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Employee> Employees { get; set; }
}

回购接口:

public interface IGenericRepository<T>
    where T : BaseEntity<T>
{
    IQueryable<T> GetAll();     // No need to async IQueryable
    Task<T> GetAsync(int id);
    Task<T> InsertAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(T entity);

    #region Possible TODOs:
    // Should this one go in the Service Layer?
    // Task<IEnumerable<T>> FindBy(Expression<Func<T, bool>> predicate);

    //Task AddRange(IEnumerable<T> entities);
    //Task RemoveRange(IEnumerable<T> entities);
    #endregion

    Task SaveAsync();
}

回购实施:

public class GenericRepository<T> : IGenericRepository<T>
    where T: BaseEntity<T>
{
    private readonly ApplicationDbContext _context;
    private DbSet<T> _entities;

    public GenericRepository(ApplicationDbContext context)
    {
        _context = context;
        _entities = context.Set<T>();
    }

    // No need to async IQueryable
    public IQueryable<T> GetAll() => _entities.AsQueryable();

    public Task<T> GetAsync(int id)
    {
        throw new NotImplementedException();
    }

现在看看签名:

public Task<T> GetAsync(int id)

这是我的困境。 设置所有实体从BaseEntity继承的重点是什么,如果我们在这里搜索GetById或GetAsync的硬编码int类型,我们可以动态获得int或guid的id?

这是一种常见的模式吗?这是代码原作者的短暂来临吗?或者我错过了这种模式的东西?
如果这是一个短暂的来临,有没有办法通过反射和搜索来获取实体ID的类型?如果是这样,性能会受到影响吗?

我是否应该删除BaseEntity上id类型的泛型,并强制框架用户始终使用框架在整个应用程序中使所有实体具有相同类型的ID?

除此之外,通用仓库的主要目的仍然存在。不必为每个实体使用相同的方法编写repo。 这里有任何建议。

0 个答案:

没有答案