Search code examples
dryioc

DryIoc registering default primitives


I have a boostrapper for the Caliburn.Micro MVVM framework where I just auto register all ViewModels in the assembly.

Some ViewModels have constructors with parameters, and I usually overwrite these manually (using the Register-parameter ifAlreadyRegistered: IfAlreadyRegistered.Replace) after my auto-registration is complete.

However, when a ViewModel has a primitive type, DryIoc automatically fills the type with a default value.

When I then manually register the ViewModel with the correct parameter, I get two registrations for the same ViewModel, where Caliburn.Micro will chose the default-filled one.

What is the proposed method of dealing with this stuff?

UPDATE:


ctor ViewModel(DependencyA depA, string[] list)

AssemblySource.Instance.SelectMany(Portable.GetAssemblyTypes)
.Where(type => type.Name.EndsWith("ViewModel"))
.ForEach(type => _container.Register(type));

This get registered as ServiceKey=DefaultKey.Of(0) registered as factory

So I now know what list should be (after the auto-registration), and I register ViewModel again, this time with a different service-key which is linked to the actual string[].

Container.Register<ViewModel>(
    made: Parameters.Of.Type<IEnumerable<string>>(typeof(string[])),
    serviceKey: "list");

This results in another registration with ServiceKey="list" registered as factory. I would like this named registration to replace the default, but I have to keep the name to actually populate the list.

The reason: Caliburn.Micro will attempt to resolve by type, and I would explicitly have to use Caliburns IoC.Get<>() to provide the key which would mean that I could not inject the ViewModel in the constructor.


Solution

  • As the first attempt, you can try to solve the problem head on: via using container-wide factory selector rule SelectKeyedOverDefaultFactory:

    var c = new Container(Rules.Default
        .WithFactorySelector(SelectKeyedOverDefaultFactory("preferable key")));
    
    c.Register<I, A>();
    c.Register<I, B>(serviceKey: "preferable key");
    c.Resolve<I>(); // will resolve I of B
    
    c.Register<X>();
    c.Resolve<X>(); // will work as before (w/out rule) by falling back to default factory.
    

    But I plan another way of solving such cases in the next version.