如何使用工厂实例化接口

How to use a factory to instantiate an interface

我有一个工厂来创建通用服务:

public static class AdPersisterFactory<TEntity>
    where TEntity : AdBase
{
    public static AdPersister<TEntity> Create(ApplicationDbContext dbContext)
    {
        AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
        IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
        AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
        return adPersister;
    }
}

我想使用 ninject(版本 3),如何将 IAdPersister 绑定到上述工厂创建的实例...这是我的 DI 代码:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();

    // I have tried the following which does not compile
    // kernel.Bind(typeof(IAdPersister<>)).ToMethod(ctx => AdPersisterFactory<>.Create(new ApplicationDbContext())); 
 }

这是针对 ASp.NET MVC 应用程序的,因此理想情况下我不想使用新的 ApplicationDbContext,而是使用 RequestScope 中存在的相同 ApplicationDbContext

我也看到了Ninject.Extensions.Factory但是我不确定how/if我可以在这种情况下使用它

如果您愿意重构为更 SOLID 的方法,并且 AdRepository<TEntity> 有类似

的支持接口
public class AdRepository<TEntity> : IAdRepository<TEntity>
    where TEntity : AdBase {

    public AdRepository(ApplicationDbContext dbContext) {
        //...
    }
}

假设...

public class AdPersister<TEntity> : IAdPersister<TEntity>
    where TEntity : AdBase {

    public AdPersister(IAdRepository<TEntity> adRepository, IAdImagePersister imagePersister) {
        //...
    }

    //...
}

然后创建开放通用依赖项的方法如下所示

private static void RegisterServices(IKernel kernel) {
    kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
    kernel.Bind<IAdImagePersister>().To<S3AdImagePersister>();
    //Open generic bind for repository and ad persister
    kernel.Bind(typeof(IAdRepository<>)).To(typeof(AdRepository<>));
    kernel.Bind(typeof(IAdPersister<>)).To(typeof(AdPersister<>));
}

现在,只要需要 persister,您就可以简单地将封闭类型注入

ctor(IAdPersister<Foo> fooPersister)

并且必要的依赖项将由容器解析和注入。

真的不需要那个静态工厂。

更新

根据评论,我仍然建议不要使用静态工厂。

如果您想将实现细节保留在您的库内部,那么将工厂设为一个实例 class

public class AdPersisterFactory<TEntity> : IAdPersisterFactory<TEntity>
    where TEntity : AdBase {

    private readonly ApplicationDbContext dbContext;

    public AdPersisterFactory(ApplicationDbContext dbContext) {
        this.dbContext = dbContext;
    }

    public IAdPersister<TEntity> Create() {
        AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
        IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
        AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
        return adPersister;
    }
}

可以在您的组合根目录中注册为开放通用。

private static void RegisterServices(IKernel kernel) {
    kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();        
    kernel.Bind(typeof(IAdPersisterFactory<>)).To(typeof(AdPersisterFactory<>));

}

并使用

ctor(IAdPersisterFactory<Foo> fooPersisterFactory) {
    IAdPersister<Foo> fooPersister = fooPersisterFactory.Create();

    //...
}