Autofac中的AsImplementedInterfaces()
在项目开发中,遇到一个问题,是这样的,我们有一个接口IConfiguration
public interface IConfiguration { string DefaultValue { get; } int Order { get; } }
另外有一个接口ITelemetryConfiguration继承它
public interface ITelemetryConfiguration : IConfiguration { string TelemetryValue {get; } }
现在有2个类,一个是LogLevel类,它继承IConfiguration接口. 另一个是TelemetrySupport类,它继承ITelemetryConfiguration接口。 如下
public class LogLevel : IConfiguration { private string logvalue; public string DefaultValue { get {return logvalue;} set {logvalue = value;} } public int Order { get {return 1;} } }
public class TelemetrySupport : ITelemetryConfiguration { public string DefaultValue { get { return "Enable"; } } public string TelemetryValue { get; set; } public int LoadOrder { get { return 2; } } }
在系统启动时用Autofac写的依赖注入中,我们原来是这样写的
using Autofac; using Module = Autofac.Module; public class IoCModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<LogLevel>().As<IConfiguration>().SingleInstance(); // 请求IConfiguration返回的是接口实现类LogLevel的实例 builder.RegisterType<TelemetrySupport>().As<ITelemetryConfiguration>().SingleInstance(); // 请求ITelemetryConfiguration返回的是接口实现类TelemetrySupport的实例 } }
然后在程序中,我们Load进来一个IEnumerable<IConfiguration>, 我们本来是期望这里面包括LogLevel和TelemetrySupport的信息。
public class ConfigurationLoader { private readonly IEnumerable<IConfiguration> configurations; public ConfigurationLoader(IEnumerable<IConfiguration> configurations) { this.configurations = configurations; } public void LoadConfiguration() {
try
{
foreach (var databaseConfig in configurations.OrderBy(x => x.Order)) // 我们预期的目的是期望从这个configurations里面里面读取出LogLevel和TelemetrySupport,但在实际debug时,发现里面只包括Loglevel,没有TelemetrySupport
{
......
}
}
catch(Exception e)
{
.......
} } }
问题就是出现在上面,我们在上面这个ConfigurationLoader类中,通过Autofac的依赖注入,把IEnumerable<IConfiguration> configurations注入进来了. 通过上面我们看到LogLevel, TelemetrySupport都是继承这个IConfiguration接口的(TelemetrySupport实现了ITelemetryConfiguration接口,而ITelemetryConfiguration接口又继承自IConfiguration接口), 这时,我理所当然的以为在上面这个类的IEnumerable<IConfiguration>会包含LogLevel和TelemetrySupport的信息,但实际debug时,发现只包含LogLevel,而没有TelemetrySupport。 问题出在哪里呢?
回到上面IocModule进行依赖注入的地方,依赖注入是这么写的
builder.RegisterType<LogLevel>().As<IConfiguration>().SingleInstance(); => 请求IConfiguration返回的是接口实现类LogLevel的实例
builder.RegisterType<TelemetrySupport>().As<ITelemetryConfiguration>().SingleInstance(); => 请求ITelemetryConfiguration返回的是接口实现类TelemetrySupport的实例
我们看到,LogLevel, 是请求IConfiguration接口时,返回的是LogLevel的实例 = > 所以上面的IEnumerable<IConfiguration> configurations会包括它
而TelemetrySupport, 是请求ITelemetryConfiguration返回的是接口实现类TelemetrySupport的实例。 而请求IConfiguration并不会返回TelemetrySupport的实例 => 所以上面的IEnumerable<IConfiguration> configurations不包括它
那么,应该怎么解决呢?
应该把builder.RegisterType<TelemetrySupport>().As<ITelemetryConfiguration>().SingleInstance() => 改为 builder.RegisterType<TelemetrySupport>().AsImplementedInterfaces().SingleInstance()
builder.RegisterType<TelemetrySupport>().AsImplementedInterfaces().SingleInstance() => 用这个AsImplementedInterfaces 表示 请求TelemetrySupport实现的任何接口(包括ITelemetryConfiguration和IConfiguration接口),都会返回TelemetrySupport的实例
改完后如下
using Autofac; using Module = Autofac.Module; public class IoCModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<LogLevel>().As<IConfiguration>().SingleInstance(); // 请求IConfiguration返回的是接口实现类LogLevel的实例 builder.RegisterType<TelemetrySupport>().AsImplementedInterfaces().SingleInstance(); // 请求TelemetrySupport实现的任何接口,都会返回实现类TelemetrySupport的实例 } }
这样,上面的IEnumerable<IConfiguration> configurations就会包含LogLevel 和 TelemetrySupport了