我有以下代码:
public class DotLessFactory
{
private LessEngine lessEngine;
public virtual ILessEngine GetEngine()
{
return lessEngine ?? (lessEngine = CreateEngine());
}
private ILessEngine CreateEngine()
{
var configuration = new LessConfiguration();
return new LessFactory().CreateEngine(configuration);
}
}
让我们假设以下内容:
- 我总是希望返回相同的 ILessEngine 实例。
- 我使用 DI 容器(我将在本示例中使用 StructureMap)来管理我的对象。
- 由于假设编号 1,我的对象的生命周期将是 Singleton。
- CreateEngine 中的代码执行通过 NuGet 包引用的代码。
- DotLess 只是一个例子。此代码可适用于任何类似的 NuGet 包。
方法一
我使用以下方法在我的 DI 容器中注册我的对象:
For<DotLessFactory>().Singleton().Use<DotLessFactory>();
For<ILessEngine>().Singleton().Use(container => container.GetInstance<DotLessFactory>().GetEngine());
For<ISomeClass>().Singleton().Use<SomeClass>();
现在我可以将 ILessEngine 添加到构造函数中,并让我的容器按照下面的代码注入它的一个实例。
public class SomeClass : ISomeClass
{
private ILessEngine lessEngine;
public SomeClass(ILessEngine lessEngine)
{
this.lessEngine = lessEngine;
}
}
方法二
引入一个公开 GetEngine 方法的 IDotLessFactory 接口。我使用以下方法在我的 DI 容器中注册我的对象:
For<IDotLessFactory>().Singleton().Use<DotLessFactory>();
For<ISomeClass>().Singleton().Use<SomeClass>();
现在我的工厂将按照下面的代码创建一个 ILessEngine 实例。
public class SomeClass : ISomeClass
{
private ILessEngine lessEngine;
public SomeClass(IDotLessFactory factory)
{
Factory = factory;
}
public IDotLessFactory Factory { get; private set; }
public ILessEngine LessEngine
{
get
{
return lessEngine ?? (lessEngine = Factory.GetEngine());
}
}
}
我的问题是:
- 就 ILessEngine 而言,方法 1 和方法 2 之间的根本区别是什么?在方法 1 中,ILessEngine 由容器管理,而在方法 2 中则不是。每种方法的优点/缺点是什么?一种方法比另一种更好吗?
- 我是否需要在 CreateEngine 方法中使用同步锁来确保任何方法的线程安全?在这种情况下,我什么时候应该/不应该使用同步锁?
- 我已经看到了在 CreateEngine 方法中使用 Activator.CreateInstance 的示例,而不是直接更新对象。有理由使用这种方法吗?这与不将工厂对象中的直接依赖项引入 NuGet 包内的对象有关吗?
- 让我们假设引用的 NuGet 包在后台与 HttpContext 一起工作。在单例范围内注册我的工厂是否会对 HttpContext 产生负面影响,或者这无关紧要,因为我认为 NuGet 包最有可能管理 HttpContext 本身的范围?
- 最后,DotLessFactory 最终将与 Bundles(Microsoft.AspNet.Web.Optimization NuGet 包)一起使用,并且 Bundle 仅在应用程序启动时实例化(不由容器管理)。Bundle 将依赖于 DotLessFactory 的注入实例。这个事实对上述问题有什么影响吗?
任何反馈都会非常有帮助。