【发布时间】:2014-07-17 15:16:10
【问题描述】:
我已经编写了一个统一接口IInterceptionBehavior 的实现来做一些日志记录。它依赖于 ILog 来进行日志记录。
public class InterceptionLoggingBehavior : IInterceptionBehavior {
public InterceptionLoggingBehavior(ILog log) {...}
...
}
我还有一个实现ILog 的ConsoleLog。
我正在尝试解析使用日志接口拦截器的接口,但它找不到ILog。即使我可以统一直接解决ILog,尝试直接解决InterceptionLoggingBehavior也不起作用:
UnityContainer container = ...
var l = container.Resolve<com.InsightSoftware.LoggingAPI.ILog>();
var b = container.Resolve<com.InsightSoftware.Logging.InterceptionLoggingBehavior>();
var p = container.Resolve<com.InsightSoftware.MetadataAPI.ITableIdentityProvider>();
解析ILog(第二行)工作正常,但解析第三行的InterceptionLoggingBehavior 或第四行的ITableIdentityProvider(我尝试登录的界面)会出现错误:
当前类型 com.InsightSoftware.LoggingAPI.ILog 是一个接口 并且无法构建。您是否缺少类型映射?
我的问题:谁能告诉我为什么当 ILog 依赖于 InterceptionLoggingBehavior 时,Unity 无法解决它?
我用来配置unity的xml,包括映射:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
<alias alias="ILog" type="com.InsightSoftware.LoggingAPI.ILog, com.InsightSoftware.LoggingAPI"/>
<alias alias="ConcreteLog" type="HubbleSandbox.ConsoleLog, HubbleSandbox" />
<alias alias="InterceptionLoggingBehavior" type="com.InsightSoftware.Logging.InterceptionLoggingBehavior, com.InsightSoftware.Logging" />
<!--More aliases-->
<containers>
<container>
<extension type="Interception" />
<!-- The type mapping that I expect to be resolved. -->
<register type="ILog" mapTo="ConcreteLog" />
<register type="ITableIdentityProvider" mapTo="TableIdentityProvider">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="InterceptionLoggingBehavior" />
</register>
<!--More registrations-->
</container>
</containers>
(请注意,我从未显式注册InterceptionLoggingBehavior,我认为它是通过在interceptionBehavior 标记中使用它来隐式注册的。)
我也尝试过在代码中配置统一性(不使用配置文件),如下所示:
UnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ILog, ConsoleLog>();
container.RegisterType<ITableIdentityProvider, TableIdentityProvider>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<InterceptionLoggingBehavior>());
// more registrations
var l = container.Resolve<ILog>();
var b = container.Resolve<ITableIdentityProvider>();
但我仍然遇到同样的错误。
编辑/更新 我做了更多的挖掘并尝试用
替换我解析InterceptionLoggingBehavior 的行
container.Resolve<InterceptionLoggingBehavior>(
new ParameterOverride(
"log",
container.Resolve<ILog>()));
我得到了错误
依赖关系解析失败,type = \"com.InsightSoftware.Logging.InterceptionLoggingBehavior\",name = \"(none)\"。
发生异常时:解析构造函数 com.InsightSoftware.Logging.InterceptionLoggingBehavior(com.InsightSoftware.LoggingAPI.ILog log) 的参数“log”。
异常是:InvalidCastException - 无法将“HubbleSandbox.ConsoleLog”类型的对象转换为“com.InsightSoftware.LoggingAPI.ILog”类型。
我已经检查过这些类型是可分配的。
public class ConsoleLog : ILog {...
和
ILog l = new ConsoleLog();
不会导致任何错误。我还检查了命名空间是否正确(ILog 是一个通用接口名称——我们使用我们的ILog 作为log4Net 中ILog 的外观——所以我进行了三次检查)。
使用
- .Net Framework 4.5
- Unity 2.1.505.0(我们在使用最新的 Unity 单声道时遇到问题)
- 一些依赖来自内部 NuGet - 不确定这是否是一个因素
【问题讨论】:
-
有趣。我的第一个想法是拦截器是基础设施的一个元素,而不是可解析的服务之一。而且我不确定 Unity 是否将相同的解析逻辑应用于您的业务类和基础设施类。换句话说,如果您以显式方式解析类型,它就可以工作。如果 Unity 在内部使用它作为拦截器,你确定它使用同一个容器来解决它吗?
-
好主意,但是当我从注册
ILog的完全相同的容器中解析InterceptionLoggingBehavior时出现错误。 -
好的,我已经创建了一个符合您的场景的最小设置,它适用于我。没有例外。我认为您正在做一些更具体的事情。
标签: c# unity-container