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.
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.