如何注册在它的构造动态字符串参数在组成根类型? [英] How can I register a type with dynamic string parameters in it's constructor at Composition root?
问题描述
我有这些构造函数:
public Configurator(string workingDirectory, string siteExclusions) : this(directory, exclusions, new ServerManager(), new DirectoryCheck())
{
}
public Configurator(string directory, string exclusions, IServerManager manager, IDirectoryCheck directoryCheck)
{
this.manager = manager;
this.directoryCheck = directoryCheck;
if (exclusions != null)
{
// do stuff
}
this.directory = directory;
}
其中,目录
和排除
通过创建代码创建一个WinForms应用程序中。例如。
Where directory
and exclusions
are created by the creating code, within a winforms application. E.g.
using (var configurator = new Configurator(this.CalculatedDirectory(), this.exclusions))
{
var output = configurator.ConfigureIIS();
this.txtOutput.Text = output;
}
我试图删除第一个构造函数和改造统一DI容器。
I am trying to remove the first constructor and retrofit the Unity DI Container. I have started to make this composition root, to be called from Program
:
public static class ApplicationRoot
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer FetchConfiguredContainer()
{
return Container.Value;
}
private static void RegisterTypes(IUnityContainer unityContainer)
{
unityContainer.RegisterType<IServerManager, ServerManager>();
unityContainer.RegisterType<IDirectoryCheck, DirectoryCheck>();
}
}
但我怎么处理字符串目录
和排除
?
我知道我可以使用新InjectionConstructor(富)
我的作文根,但我不知道该点的值。
I know I can use new InjectionConstructor("foo")
in my Composition Root, but I don't know the values at that point.
推荐答案
我问了一个类似的问题,前一阵子 - 的与其他构造与团结参数解析
I asked a similiar question a while ago - Resolve with parameter from other constructor with unity
史蒂芬,以便优雅所说的那样:
As Steven so elegantly put it:
在换句话说,你的[变量名称]参数是运行时数据。注入
运行时数据到组件的初始化期间的组件是
反模式。
In other words, your [variable name] parameter is runtime data. Injecting runtime data into components during the components' initialization is an anti-pattern.
我解决它是创建保存值的容器的方法。在我来说,我是能够绑定到WCF的上下文。但它可能是保持一个特定的线程,请求或会话,而不是
The way I solved it was to create a container that hold the value. In my case I was able to bind it to the WCF-context. But it could be hold for a specific thread, request or session instead.
下面是一个例子:
public interface IOperationContext<T>
{
IDictionary<string, T> Items { get; }
}
public class ThreadOperationContext<T> : IOperationContext<T>
{
[ThreadStatic]
private static Dictionary<string, T> _items;
public IDictionary<string, T> Items
{
get
{
if (_items == null)
{
_items = new Dictionary<string, T>();
}
return _items;
}
}
}
public class WcfOperationContext<T> : IExtension<OperationContext>
{
private readonly IDictionary<string, T> _items;
private WcfOperationContext()
{
_items = new Dictionary<string, T>();
}
public IDictionary<string, T> Items
{
get { return _items; }
}
public static WcfOperationContext<T> Current
{
get
{
WcfOperationContext<T> context = OperationContext.Current.Extensions.Find<WcfOperationContext<T>>();
if (context == null)
{
context = new WcfOperationContext<T>();
OperationContext.Current.Extensions.Add(context);
}
return context;
}
}
public void Attach(OperationContext owner) { }
public void Detach(OperationContext owner) { }
}
/// <summary>
/// Provides a collection that will be unique for every operation context.
/// </summary>
/// <typeparam name="T"></typeparam>
public class WcfOperationContextWrapper<T> : IOperationContext<T>
{
public IDictionary<string, T> Items
{
get { return WcfOperationContext<T>.Current.Items; }
}
}
然后你可以注入 IOperationContext<串GT;
当变量<应该是code>工作目录来进行设置。然后你可以注入它在你需要它,并为您的变量设置实施
Then you can inject an IOperationContext<string>
when the variable workingDirectory
is supposed to be set. Then you can inject it in the implementation where you need it and have the variable set for you.
例如:
public class MySetter
{
public MySetter(IOperationContext<string> stringContainer)
{
stringContainer["workingDirectory"] = "foo";
}
}
public class MyGetter
{
public MyGetter(IOperationContext<string> stringContainer)
{
var workingDirectory = stringContainer["workingDirectory"];
}
}
上面的代码将与WCF和线程独特的工作流程。但是,正如我敢肯定你知道,对于一个特定的线程绑定信息时,一些风险。但我希望它可以引导你在正确的方向。问题的关键是将其绑定到一个容器,使用容器而不是字符串。您可以使用会话
而不是 ThreadStatic
如果它的用户特定的等等。
The code above will work with WCF and Thread-unique processes. But, as I'm sure you know, there are several risks when binding information for a specific thread. But I hope it can guide you in the right direction. The point is to bind it to a container and use the container instead of a string. You can use Session
instead of ThreadStatic
if it's user specific and so on.
这篇关于如何注册在它的构造动态字符串参数在组成根类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!