I have a situation where I want custom code to be able to override existing registrations. For example I have an interface,
public interface IInterface{ int Num {get;set;}
That by default resolves to,
public class CoreClass: IInterface{...}
(NB. this registration is done by SMs Scan() functionality (WithDefaultConventions, SingleImplementationsOfInterface)
Now I want a piece of custom code to join SMs Initialize process and override the existing IInterface registration with its own implementation,
public class CustomClass: IInterface {...}
Here's the issue. If I do this registration by also doing a Scan() on my custom assembly and using same SM conventions as above (WithDefaultConventions, SingleImplementationsOfInterface) then at runtime when I do a GetInstance I get the exception,
No Default Instance defined for PluginFamily IInterface
But when I add the overriding registration by using,
x.For<IInterface>().Use<CustomClass>()
It all works.
Also, when I interrogate the container using,
ObjectFactory.WhatDoIHave()
Then I get slightly different results depending on the method of registration. WhatDoIHave() basically shows you for a PLUGINTYPE which things are registered. The Name column shows the concrete types registered. When I Scan() and there are multiple implementations then I see the .Net type name of the concrete types found. But when I use the For<>() method I see the multiple implementations as above but also a GUID next to the concrete type used in the For<>() statement (I'm assuming this is indicating the default registration?)
Now a lot of SO posts indicate that last registration wins (which is the behaviour I want) but what I want to know is if that only applies to explicit registrations (i.e. using For<>). When I Scan() can I assume that SM is acting in a more "non-deterministic" way and not guaranteeing the last found implementation wins or am I missing something?
Thanks & sorry for the lengthy post!
Edit: [Sample registration code as requested]
ObjectFactory.Initialize(x =>
{
x.AddRegistry<CoreRegistry>();
x.AddRegistry<ClientRegistry>();
});
public class CoreRegistry : Registry
{
public CoreRegistry()
{
//Presentation
Scan(x =>
{
x.AssemblyContainingType<SomeCoreType>();
x.WithDefaultConventions();
x.SingleImplementationsOfInterface();
x.AddAllTypesOf<ConfigurableEntityViewModel>();
});
// Domain
Scan(x =>
{
x.AssemblyContainingType<AnotherCoreType>();
x.WithDefaultConventions();
x.SingleImplementationsOfInterface();
});
...
}
public class ClientRegistry : Registry
{
public ClientRegistry()
{
//Presentation
Scan(x =>
{
x.AssemblyContainingType<SomeClientType>();
x.WithDefaultConventions();
x.SingleImplementationsOfInterface();
});
}
}
So I was hoping that concrete implementations (e.g. of IInterface) from ClientRegistry would be registered last in the container and would therefore be the "default" registration and in turn be returned when calling GetInstance(). But this is not the case, it throws an error as described above.