c# - 使用依赖注入(inject)时避免单例存储库(DryIoc)

标签 c# dependency-injection singleton repository-pattern dryioc

我最近创建了一个解决方案,并想尝试使用 DryIoC 容器来处理依赖项注入(inject)。现在,与我使用过的许多其他 DI 解决方案一样,对象重用的默认范围是 transient。然而,这似乎对我正在使用的存储库模式的实现造成了问题,因为如果引用的类实现了 IDisposable,DryIoC(和许多其他解决方案)无法将绑定(bind)注册为 transient 。因此,我暂时求助于使用 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
}

最佳答案

文档 here 解释了为什么一次性 transient 是问题所在,以及为什么以这种方式选择 DryIoc 默认行为。基本上,这种行为是为了将问题告知您,而不是默默地接受它。

关于其他容器,没有强烈偏好特定的一次性 transient 处理。这是与 Microsoft.Extensions.DependencyInjection 相关的讨论,有 Autofac、StructureMap 和其他容器开发人员参与。

顺便说一句,DryIoc 错误消息包含如何选择加入问题的提示。

关于c# - 使用依赖注入(inject)时避免单例存储库(DryIoc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46424751/

相关文章:

c# - LongListSelector 数据虚拟化

php - Laravel、依赖注入(inject)和 Eloquent

elasticsearch - 释放Elasticsearch连接

objective-c - Apple 文档中的 Singleton 示例实际上做了什么?

java - Singleton Java 类可以有静态常量变量吗?声纳 Lint 错误

c# - (嵌套)自定义对象列表中的列表

c# - 表单提交后保持URL不变

c# - 在 .Net 中 Hook

c# - 在泛型类中注入(inject)依赖项时出错

c# - 增加一个参数DI注册