使用依赖项注入时避免使用单一存储库(DryIoc [英] Avoid singleton repository (DryIoc) when using dependency injection

查看:95
本文介绍了使用依赖项注入时避免使用单一存储库(DryIoc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近创建了一个解决方案,我想我应该尝试一下DryIoC容器来处理依赖项注入。现在,与我使用的许多其他DI解决方案一样,对象重用的默认作用域是瞬时。然而,这似乎给我正在使用的存储库模式的实现带来了问题,因为如果引用的类实现了IDisposable,则DryIoC(和许多其他解决方案)不能将绑定注册为临时绑定。因此,我暂时求助于向Reuse.Singleton注册我的存储库。这对我来说绝对是一种代码气味,所以我希望有人能给我一些如何避免这种情况的建议--例如,可能是我在创建存储库方面做得不好。

以下是我用来创建IOC容器的代码:

private static Container ConstructNewContainer()
{
    var container = new Container(Rules.Default);
    container.Register(Made.Of(() => SettingsFactory.CreateSettings()));    
    container.Register<IRepository<tblMailMessage>, MailMessageRepository>(Reuse.Singleton);
    container.Register<IRepository<ProcessedMailMessages>, ProcessedMailMessageRepository>(Reuse.Singleton);
    container.Register<IParser, EmailParser>();
    container.Register<IMonitor, DatabaseMonitor>();
    return container;
}

...和一个存储库实现示例:

public interface IRepository<T>
{
    void Insert(T objectToInsert);

    void Delete(int id);

    void Update(T objectToUpdate);

    void Save();

    T GetById(long id);

    IEnumerable<T> Get();

    T Last();

    bool Exists(int id);
}

public class MailMessageRepository : IRepository<tblMailMessage>, IDisposable
{
    private bool _disposed;
    private readonly CoreDataModel _model;

    public MailMessageRepository()
    {
        _model = new CoreDataModel();
    }

    public void Delete(int id)
    {
        var objectToDelete = _model.tblMailMessages.Find(id);
        if (objectToDelete != null) _model.tblMailMessages.Remove(objectToDelete);
    }

    public void Update(tblMailMessage objectToUpdate) => _model.Entry(objectToUpdate).State = EntityState.Modified;

    public void Save() => _model.SaveChanges();

    public IEnumerable<tblMailMessage> Get() => _model.tblMailMessages.ToList();

    public tblMailMessage Last() => _model.tblMailMessages.OrderByDescending(x => x.DateSubmitted).FirstOrDefault();

    public bool Exists(int id) => _model.tblMailMessages.SingleOrDefault(x => x.MailMessageID == id) != null;

    public void Insert(tblMailMessage objectToInsert) => _model.tblMailMessages.Add(objectToInsert);

    public tblMailMessage GetById(long id) => _model.tblMailMessages.SingleOrDefault(x => x.MailMessageID == id);

    #region Dispose

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (!disposing)
            {
                _model.Dispose();
            }
        }

        _disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

推荐答案

根据the documentation,您有3个选择:

  1. 不允许注册一次性临时服务。默认DryIoc行为。

     container.Register<X>(); // will throw exception  
    
  2. 允许注册一次性暂态,但将处置服务的责任委派给容器用户。

     container.Register<X>(setup: Setup.With(allowDisposableTransient: true));
    
     // or allow globally for all container registrations:
     var container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient());
    
     container.Register<X>(); // works, but dispose is up to User
    
  3. 在其所有者重用作用域(如果有)中跟踪(存储)可释放瞬时依赖项,或在当前打开作用域(如果有)中跟踪已解析的可释放瞬时依赖项。

     container.Register<X>(setup: Setup.With(trackDisposableTransient: true));
    
     // or track globally for all container registrations:
     var container = new Container(rules => rules.WithTrackingDisposableTransients());
    
     // will be tracked in XUser parent in singleton scope and disposed with container as all singletons
     container.Register<XUser>(Reuse.Singleton);
     container.Register<X>();  
    
     // or tracking in open scope
     using (var scope = container.OpenScope())
         scope.Resolve<X>; // will be disposed on exiting of using block
    

正如您在上面看到的,默认行为要求您在使用临时生活方式时显式处置。

但他们遗漏了第四个选项,即寻找另一个DI容器。我从来没有使用过DryIoC,但这似乎太让人担心了,因为你不必使用其他容器。通常,选择正确的生存期决定了何时处置实例。

这篇关于使用依赖项注入时避免使用单一存储库(DryIoc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆