与一次性对象一起注入和使用(重置对象属性)

本文关键字:对象 属性 一次性 一起 注入 | 更新日期: 2023-09-27 18:30:35

在引入依赖注入之前,我有一个类,看起来像这样:

public class Widget
{
    public Widget Create()
    {
        using (DataProvider dataProvider = new DataProvder())
        {
            dataProvider.AddInput("name", name);
            dataProvider.AddInput("path", path);
            dataProvider.AddInput("dateCreated", DateTime.UtcNow);
            using (var reader = _dataProvider.ExecuteReader("usp_widget_create"))
            {
                reader.Read();
                return new Widget(reader);
            }
        }
    }
}

然后我使用 Ninject 引入了依赖关系注入,我的类现在看起来像这样,所以我不会创建对 DataProvider 类的依赖关系。

public class Widget
{
    IDataProvider _dataProvider;
    public Widget(IDataProvider dataProvider)
    {
        _dataProvider = dataProvider;
    }
    public Widget Create()
    {
        _dataProvider.AddInput("name", name);
        _dataProvider.AddInput("path", path);
        _dataProvider.AddInput("dateCreated", DateTime.UtcNow);
        using (var reader = _dataProvider.ExecuteReader("usp_widget_create"))
        {
            reader.Read();
            return new Widget(reader);
        }
    }
}

新类的问题在于,第一,数据提供程序不会被释放,第二,数据提供程序的属性不会被重置。因此,如果我从同一对象调用 Create 两次,它将复制参数并引发异常。我知道我可以通过清除参数来明确解决第二个问题,但我觉得必须有一种更通用的方法,我错过了一些东西。

这种情况应该如何解决?

与一次性对象一起注入和使用(重置对象属性)

您非常想使用的模式是具有抽象工厂模式的依赖注入。此工厂模式允许您在需要时动态创建实例。这样做是很常见的事情。

定义允许您创建提供实例的工厂。

public interface IProviderFactory
{
    T Create<T>();
}

实现可以很简单,如下所示。

public class ProviderFactory : IProviderFactory
{
    private readonly IKernel _kernel;
    public ProviderFactory(IKernel kernel)
    {
        _kernel = kernel;
    }
    public T Create<T>()
    {
        var instance = _kernel.Get<T>();
        return instance;
    }
}

现在更改您的小部件以接受工厂而不是 IDataProvider

public class Widget
{
    readonly IProviderFactory _factory;
    public Widget(IProviderFactory factory)
    {
        _factory = factory;
    }
    public Widget Create()
    {
        var provider = _factory.Create<IDataProvider>();
        provider.AddInput("name", "name");
        provider.AddInput("path", "path");
        provider.AddInput("dateCreated", DateTime.UtcNow);
        //.....
    }
}

请注意,每次调用 Create() 都会解析 IDataProvider 的新实例。

VaR 提供程序 = _factory。创建();

内核注册如下所示。

        using (IKernel Kernel = new StandardKernel())
        {
            Kernel.Bind<IDataProvider>().To<DataProvider>();
            Kernel.Bind<IProviderFactory>()
             .To<ProviderFactory>().WithConstructorArgument(typeof(IKernel), Kernel);
            var widget = Kernel.Get<Widget>();
            widget.Create();
            widget.Create();
        }

沿着线的东西应该为你提供可能的解决方案的方向。