在我介绍依赖注入之前,我有一个类,如下所示:
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两次,它将复制参数并抛出异常。我知道我可以通过清除参数明确解决第二个问题,但我觉得必须有一个更普遍的方法,我错过了一些东西。
如何解决这种情况?
答案 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();
}
沿线的某些内容应为您提供可能解决方案的方向。