asp.net core 實現一個簡單的倉儲


一直有自己寫個框架的想法,但是一直沒有行動起來,最近比較閑,正好可以開工了.

現在已經完成了兩部分.1.一個簡單倉儲,實現使用的是ef 2.IOC部分,這里是把內置的ioc替換成了aotofac,這部分感覺還是有一點缺陷的.下面說

倉儲部分

這里主要是接口是實現,目前使用ef實現了倉儲的接口.看一下代碼

    public interface IRepository<TEntity, TPrimaryKey>
        where TEntity : class
    {
        #region Select/Get/Query

        IQueryable<TEntity> GetAll();

        IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors);

        List<TEntity> GetAllList();

        Task<List<TEntity>> GetAllListAsync();

        List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate);

        Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);

        T Query<T>(Func<IQueryable<TEntity>, T> queryMethod);

        TEntity Get(TPrimaryKey id);

        Task<TEntity> GetAsync(TPrimaryKey id);

        TEntity Single(Expression<Func<TEntity, bool>> predicate);

        Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate);

        TEntity FirstOrDefault(TPrimaryKey id);

        Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id);

        TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);

        Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);

        TEntity Load(TPrimaryKey id);

        #endregion

        #region Insert

        TEntity Insert(TEntity entity);

        Task<TEntity> InsertAsync(TEntity entity);

        #endregion

        #region Update

        TEntity Update(TEntity entity);

        Task<TEntity> UpdateAsync(TEntity entity);

        TEntity Update(TPrimaryKey id, Action<TEntity> updateAction);

        Task<TEntity> UpdateAsync(TPrimaryKey id, Func<TEntity, Task> updateAction);

        #endregion

        #region Delete

        void Delete(TEntity entity);

        Task DeleteAsync(TEntity entity);

        void Delete(TPrimaryKey id);

        Task DeleteAsync(TPrimaryKey id);

        void Delete(Expression<Func<TEntity, bool>> predicate);

        Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);

        #endregion

        #region Aggregates

        int Count();

        Task<int> CountAsync();

        int Count(Expression<Func<TEntity, bool>> predicate);

        Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);

        long LongCount();

        Task<long> LongCountAsync();

        long LongCount(Expression<Func<TEntity, bool>> predicate);

        Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate);

        #endregion
    }

下面是實現的部分代碼,代碼比較占版面,就不貼全了.

    public abstract class RepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
        where TEntity : class
    {
        public abstract IQueryable<TEntity> GetAll();

        public abstract IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors);

        public virtual List<TEntity> GetAllList()
        {
            return GetAll().ToList();
        }

        public virtual async Task<List<TEntity>> GetAllListAsync()
        {
            return await Task.FromResult(GetAllList());
        }
    }
    public class EfRepositoryBase<TDbContext, TEntity, TPrimaryKey> : RepositoryBase<TEntity, TPrimaryKey>
        where TEntity : class
        where TDbContext : DbContext
    {
        public virtual TDbContext Context { private set; get; }

        public virtual DbSet<TEntity> Table => Context.Set<TEntity>();

        public EfRepositoryBase(TDbContext context)
        {
            Context = context;
        }

        public override IQueryable<TEntity> GetAll()
        {
            return Table;
        }

        public override IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors)
        {
            if (propertySelectors == null)
            {
                return GetAll();
            }

            var linq = GetAll();

            foreach (var item in propertySelectors)
            {
                linq = linq.Include(item);
            }

            return linq;
        }
    }

注意看EfRepositoryBase繼承了RepositoryBase,而RepositoryBase實現了IRepository.這里的RepositoryBase是所有實現的基類.GetAllList虛方法直接調用了抽象方法GetAll,這樣在EfRepositoryBase中就可以減少很多代碼了.

這里有個坑 EfRepositoryBase 是不能直接注冊到IOC中的,因為EfRepositoryBase和IRepository的泛型參數個數不一致,ioc不能找到多出的一個泛型的值.使用倉儲的時候繼承EfRepositoryBase把dbcontext傳進去就好了

public class TestRepository<TEntity, TPrimaryKey> : EfRepositoryBase<TestContext, TEntity, TPrimaryKey> where TEntity : class
{
    public TestRepository(TestContext context)
        : base(context)
    {
    }
}

IOC部分

asp.net core 微軟提供了一個簡單的IOC,但是接口比較少,替換成我們熟悉的ioc框架就方便多了. asp.net core 也有很方便的替換ioc的方法.簡單說就是修改ConfigureServices方法的返回值為IServiceProvider.我使用了autofac,下面看代碼.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    return services.AddLuna<AutofacModule>();
}


public static IServiceProvider AddLuna<TModule>([NotNull]this IServiceCollection services)
    where TModule : IModule, new()
{
    var builder = new ContainerBuilder();
    builder.Populate(services);
    builder.RegisterModule<TModule>();

    return new AutofacServiceProvider(builder.Build());
}

public class AutofacModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<TestContext>();

        builder.RegisterGeneric(typeof(TestRepository<,>)).As(typeof(IRepository<,>))
            .InstancePerLifetimeScope();
    }
}

這里的Module和IModule是autofac的,功能已經實現了,但是作為框架來說直接暴露了autofac的東西顯然是不合適的,下一步要實現一個框架自身的模塊加載方式.

最后.誰家公司在招聘程序猿啊,北京的,求聯系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM