为什么IContainer.IsRegistered(类型serviceType)添加注册?

时间:2012-05-14 15:19:42

标签: autofac

为什么IContainer.IsRegistered(类型serviceType)会添加注册?

Type serviceType = typeof (string[]);
int rc = container.ComponentRegistry.Registrations.Count();
container.IsRegistered(serviceType);
int rc2 = container.ComponentRegistry.Registrations.Count();
Assert.AreEqual(rc, rc2);

上述行为可能会产生以下副作用:

public class Test
{
      public Entity[] Entities { get; set; }
}
//...
var bldr = new ContainerBuilder();
bldr.RegisterModule<ArraysInjectionGuardModule>();
var container = bldr.Build();
var t = new Test();
container.InjectProperties(t);
Assert.IsNull(t.Entities);

因为container.InjectProperties(...);调用container.IsRegistered(..)并传递typeof(Entity[])作为参数,所以使用空数组初始化t.Entities。 当我发现这种行为时,我有点困惑。

1 个答案:

答案 0 :(得分:0)

我发现上述行为是by design

这是一种避免注入空阵列的解决方法 它使用反射,因此请自行承担风险 请注意降低分辨率性能。 您只需注册以下模块:

containerBuilder.RegisterModule<ArraysInjectionGuardModule>();

class ArraysInjectionGuardModule : Module
    {
        protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
                                                              IComponentRegistration registration)
        {
            registration.Activating += (s, e) =>
                                        {
                                            var ts = e.Component.Services.Single() as TypedService;
                                            if (ts != null && ts.ServiceType.IsArray &&
                                                !e.Context.IsRegistered(ts.ServiceType.GetElementType()))
                                            {
                                                FieldInfo t = e.GetType().GetField("_instance",
                                                                                   BindingFlags.Instance | BindingFlags.NonPublic);
                                                t.SetValue(e, null);
                                            }
                                        };
        }
    }