【问题标题】:Repository Factory with Ninject带有 Ninject 的存储库工厂
【发布时间】:2014-03-11 09:27:02
【问题描述】:

在我的应用程序中,我使用存储库进行 CRUD 操作。在所有实体中,有些根本不能删除,有些实体(实现ISoftDeletable)只能软删除,有些实体(实现IPermanentDeletable)可以永久删除。 (我正在关注这个帖子Generic Repository with Soft Delete Feature的答案)

我有 3 个相互继承的存储库,如下所示

BaseRepository : IRepository

SoftDeleteRepository : BaseRepository, ISoftDeleteRepository

PermanentDeleteRepository : BaseRepository, IPermanentDeleteRepository

我的问题是,我不想为每个不同类型的实体做单独的绑定,比如

kernel.Bind(typeof(IRepository<Company>)).To(typeof(BaseRepository<Company>));
kernel.Bind(typeof(IRepository<Country>)).To(typeof(PermanentDeleteRepository<Country>));
kernel.Bind(typeof(IRepository<Contact>)).To(typeof(SoftDeleteRepository<Contact>));

但是,相反,我想以某种方式使IRepository 的所有绑定都进入工厂并根据其通用参数所采用的实体类型实例化存储库,并将其注入控制器。

有可能实现吗?

【问题讨论】:

    标签: c# entity-framework asp.net-mvc-4 ninject


    【解决方案1】:

    因此,您可以通过以下方式实现它,同时仍将IRepository&lt;XYZ&gt; 注入消费者:

    public interface ISoftDeletable
    {
    }
    
    public interface IPermanentDeleteable
    {
    }
    
    public interface IRepository<TEntity>
    {
    }
    
    public class PermanentDeletableRepository<TEntity> : IRepository<TEntity>
        where TEntity : IPermanentDeleteable
    {
    }
    
    public class SoftDeletableRepository<TEntity> : IRepository<TEntity>
        where TEntity : ISoftDeletable
    {
    }
    
    public class RepositoryModule : NinjectModule
    {
        public override void Load()
        {
            this.Bind(typeof(IRepository<>))
                .To(typeof(PermanentDeletableRepository<>))
                .When(IsRequestForRepositoryOfEntityImplementing<IPermanentDeleteable>);
    
            this.Bind(typeof(IRepository<>))
                .To(typeof(SoftDeletableRepository<>))
                .When(IsRequestForRepositoryOfEntityImplementing<ISoftDeletable>);
        }
    
        public static bool IsRequestForRepositoryOfEntityImplementing<TInterface>(IRequest request)
        {
            Type entityType = GetEntityTypeOfRepository(request.Service);
            return ImplementsInterface<TInterface>(entityType);
        }
    
        public static Type GetEntityTypeOfRepository(Type repositoryType)
        {
            // target.Type must be IRepository<"AnyEntity">
            return repositoryType.GetGenericArguments().Single();
        }
    
        public static bool ImplementsInterface<TInterface>(Type type)
        {
            return typeof(TInterface).IsAssignableFrom(type);
        }
    }
    

    我通过单元测试验证了它的工作原理:

        public class SomeSoftDeletableEntity : ISoftDeletable
        {
        }
    
        [Fact]
        public void RepositoryBinding()
        {
            var kernel = new StandardKernel();
            kernel.Load<RepositoryModule>();
    
            IRepository<SomeSoftDeletableEntity> repository = kernel.Get<IRepository<SomeSoftDeletableEntity>>();
    
            repository.Should().BeOfType<SoftDeletableRepository<SomeSoftDeletableEntity>>();
        }
    

    【讨论】:

    • 关于public override void Load()。如果我还有其他类型的存储库怎么办?如,任何不实现ISoftDeletableIPermanentDeletable 的实体都应该使用BaseRepository。为了实现这一点,调用 base.Load() 作为我们覆盖的 Load 方法中的第一件事就足够了吗?
    • 对不起,我发布的代码有些不完整。 Load 方法应该是Module : NinjectModule 的一部分,然后由IKernel.Load&lt;Module&gt;() 加载。您也可以使用IKernel.Bind(...) 创建绑定——没关系。关于“其他”实体的问题:您应该创建第三个绑定,默认绑定:IBindingRoot.Bind(typeof(IRepository&lt;&gt;)).To(typeof(BaseRepository&lt;&gt;));。当有多个绑定时,ninject 会先使用一个带.When(...) 的绑定,然后再使用一个不带的绑定。
    • 非常感谢您的帮助。它按我的意愿工作。
    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多