Ninject和使用一次性对象(重置对象属性)

时间:2014-11-14 23:24:02

标签: c# dependency-injection ninject

在我介绍依赖注入之前,我有一个类,如下所示:

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);
        }
    }
}

新类的问题是,一个,DataProvider不会被处理,两个,DataProvider的属性不会被重置。因此,如果我从同一个对象调用Create两次,它将复制参数并抛出异常。我知道我可以通过清除参数明确解决第二个问题,但我觉得必须有一个更普遍的方法,我错过了一些东西。

如何解决这种情况?

1 个答案:

答案 0 :(得分:1)

您想要使用的模式是Abstract Factory Pattern的依赖注入。 只要您需要,此工厂模式允许您dynamically create instances。这样做很常见。

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

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;
    }
}

现在更改您的Widget以接受Factory而不是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 provider = _factory.Create();

Kernal注册如下所示..

        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();
        }

沿线的某些内容应为您提供可能解决方案的方向。