我有以下扩展方法,它(自然地)存在于静态类中。
public static class MyExtensions
{
[Dependency]
private static IMyDataContext _myDataContext { get; set; }
public static void MyExtensionMethod(this MyType myType)
{
// do stuff
_myDataContext.DoAwesomeThing();
}
}
_myDataContext
对象 null 。
通常我会使用UnityContainer
来注册类型,但由于这是一个静态类,我不能这样做。
我需要什么来实例化_ myDataContext
,以便在需要时它不为空?
答案 0 :(得分:19)
正如您已经提到的,由于它是静态的,Unity无法用于解析类。有几种选择。我个人最喜欢的是使用抽象工厂模式。我倾向于调整模式,以便与DI合作。
工厂通常看起来像这样:
/// <summary>
/// Creates an IMyDataContext instance
/// </summary>
public static class MyDataContextFactory
{
/// <summary>
/// The factory used to create an instance
/// </summary>
static Func<IMyDataContext> factory;
/// <summary>
/// Initializes the specified creation factory.
/// </summary>
/// <param name="creationFactory">The creation factory.</param>
public static void SetFactory(Func<IMyDataContext> creationFactory)
{
factory = creationFactory;
}
/// <summary>
/// Creates a new IMyDataContext instance.
/// </summary>
/// <returns>Returns an instance of an IMyDataContext </returns>
public static IMyDataContext CreateContext()
{
if (factory == null) throw new InvalidOperationException("You can not create a context without first building the factory.");
return factory();
}
}
在您的引导过程中(无论您何时设置服务注册),都可以初始化工厂以解决依赖关系。
MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());
现在,在您的扩展方法中,您将获取上下文。
public static class MyExtensions
{
public static void MyExtensionMethod(this MyType myType)
{
MyDataContextFactory.CreateContext().DoAwesomeThing();
}
}
您的Unity注册上下文,如果有条件解决它,可以处理服务的各种不同配置。如果上下文可能由Unity以外的其他东西设置,那么该所有者只能传入扩展方法将使用的新委托。
我倾向于避免将容器本身传递到我的工厂,因为这会开始将容器紧密耦合到我的应用程序。如果我要将任何东西送到工厂,我宁愿它是一个用于通过DI解决的工厂代表,而不是通过DI容器。