0

IContainer.IsRegistered(Type 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 は空の配列で初期化されます。この動作を発見したとき、私は少し混乱しました。

4

1 に答える 1

0

上記の動作は設計によるものであることがわかりました

空の配列の挿入を回避するための回避策を次に示します。
リフレクションを使用するため、このアプローチは自己責任で使用してください。解像性能が低下し
ますのでご注意ください。次のモジュールを登録するだけです。

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);
            }
        };
    }
}
于 2012-05-15T10:24:12.173 に答える