Tur*_*ete 2 enterprise-library ioc-container unity-container
对不起,这是一个非常特殊的主题,所以这可能不是很多人感兴趣的.:-(
但是,我需要做以下事情:
我有一个应用程序,它提供了某种控制台窗口的日志记录(它是一个WPF窗口,因为应用程序需求,因为应用程序需要看起来华而不实 - 我们的特殊客户要求并在每次我们见面时讨论它)
为了提供与线程无关的日志记录,我创建了一个接口/实现对"IGUIController"/"GUIController"
到现在为止还挺好.一切都很好.
然而:
到目前为止,我的解决方案是让一个黑客,旧的skool代码闻到单身式 - 风格"当前" - 我的GUIController属性(是的,我很惭愧,我知道这很糟糕),我这样调用:
GUIController.Current.Log(message);
Run Code Online (Sandbox Code Playgroud)
显然,这是一个禁忌.
因此,正确的方法是注入依赖(当然).但是,当我这样做时,我得到了投诉(运行时),我没有为我的GUITraceListener类提供0(零)参数的构造函数.
事实上,我在这里得到:
EnterpriseLibraryContainer.ConfigureContainer(configurator,
ConfigurationSourceFactory.Create());
Run Code Online (Sandbox Code Playgroud)
投诉是:
ArgumentException未处理无法为GUITraceListener找到合适的0参数构造函数
这真的很糟糕.我的意思是,Unity是企业库的一部分,为什么这些人不会简单地添加注入我的依赖项的可能性?
澄清:
我最终想要的是:
/// <summary>
/// Constructor
/// </summary>
/// <param name="guiController"></param>
public GUITraceListener(IGUIController guiController)
{
// Store the dependencies
this.m_GUIController = guiController;
}
Run Code Online (Sandbox Code Playgroud)
Entlib 5 确实有能力做到这一点.我猜你的侦听器类上有[ConfigurationElementType(typeof(CustomTraceListenerData)],对吗?
Entlib 5设计为独立于容器.因此,我们不能依赖任何类型的自动布线语义,因为每个容器都以不同的方式执行.所以你需要告诉Entlib要调用哪个构造函数,以及应该注入哪些依赖项.这是通过配置数据类完成的.
我打了一个快速的例子.这是跟踪侦听器 - 没有太多特别之处:
[ConfigurationElementType(typeof(GuiTraceListenerData))]
public class GuiTraceListener : TraceListener
{
private readonly ILogFormatter formatter;
private readonly IGuiController guiController;
public GuiTraceListener()
: this(string.Empty, null, null)
{
}
public GuiTraceListener(string name)
: this(name, null, null)
{
}
public GuiTraceListener(string name, ILogFormatter formatter, IGuiController guiController) : base(name)
{
this.formatter = formatter;
this.guiController = guiController;
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id,
object data)
{
if ((Filter == null) || Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
{
if (data is LogEntry)
{
if (formatter != null)
{
Write(formatter.Format(data as LogEntry));
}
else
{
base.TraceData(eventCache, source, eventType, id, data);
}
}
else
{
base.TraceData(eventCache, source, eventType, id, data);
}
}
}
public override void Write(string message)
{
guiController.Log(message);
}
public override void WriteLine(string message)
{
guiController.Log(message);
}
}
Run Code Online (Sandbox Code Playgroud)
有趣的部分是在GuiTraceListenerData类中:
public class GuiTraceListenerData : TraceListenerData
{
private const string formatterNameProperty = "formatter";
public GuiTraceListenerData()
: this("unnamed", null, TraceOptions.None)
{
}
public GuiTraceListenerData(string name)
: this(name, null, TraceOptions.None)
{
}
public GuiTraceListenerData(string name, string formatterName)
: this(name, formatterName, TraceOptions.None)
{
}
protected GuiTraceListenerData(string name, string formatterName, TraceOptions traceOutputOptions)
: base(name, typeof (GuiTraceListener), traceOutputOptions, SourceLevels.All)
{
ListenerDataType = typeof (GuiTraceListenerData);
Formatter = formatterName;
}
[ConfigurationProperty(formatterNameProperty, IsRequired = false)]
[Reference(typeof(NameTypeConfigurationElementCollection<FormatterData, CustomFormatterData>), typeof(FormatterData))]
public string Formatter
{
get { return (string) base[formatterNameProperty]; }
set { base[formatterNameProperty] = value; }
}
protected override Expression<Func<TraceListener>> GetCreationExpression()
{
return () =>
new GuiTraceListener(Name,
Container.ResolvedIfNotNull<ILogFormatter>(Formatter),
Container.Resolved<IGuiController>());
}
}
Run Code Online (Sandbox Code Playgroud)
特别是,看看GetCreationExpression方法.那告诉entlib要创建这个config new表示的对象,调用该构造函数,并解析格式化程序(如果指定了一个)和IGuiController.
然后,在我的测试应用程序(我使用Winforms只是为了快)我初始化我的容器和应用程序像这样:
static void Main()
{
var container = new UnityContainer()
.AddNewExtension<EnterpriseLibraryCoreExtension>()
.RegisterType<IGuiController, MessageBoxGuiController>();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(container.Resolve<Form1>());
}
Run Code Online (Sandbox Code Playgroud)
我的Form1类将LogWriter作为构造函数参数.
关于如何构建Entlib 5的好处是,在执行此操作时您将获得几乎自动的配置工具支持 - 无需编写单独的配置节点.您只需要运行时配置元素 - 只需使用配置工具将DLL复制到同一目录中,它就可以将其取出.
无论如何,从这里开始它就行了.
希望这可以帮助.如果您想了解更多细节,请给我发一条线,然后我就可以向您发送整个工作项目.
-克里斯
| 归档时间: |
|
| 查看次数: |
1930 次 |
| 最近记录: |