Consider the following
builder.Register(c => new A());
builder.Register(c => new B());
builder.Register(c => new C());
B
I needed to resolve based on some context. So slight variation...
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(ISomeStrategy)))
.Where(t => typeof(ISomeStrategy).IsAssignableFrom(t))
.AsSelf();
builder.Register<Func<SomeEnum, ISomeStrategy>>(c =>
{
var types = c.ComponentRegistry.Registrations
.Where(r => typeof(ISomeStrategy).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Activator.LimitType);
ISomeStrategy[] lst = types.Select(t => c.Resolve(t) as ISomeStrategy).ToArray();
return (someEnum) =>
{
return lst.FirstOrDefault(x => x.CanProcess(someEnum));
};
});
Then for your class using the strategy
public SomeProvider(Func<SomeType, ISomeStrategy> someFactory)
{
_someFactory = someFactory;
}
public void DoSomething(SomeType someType)
{
var strategy = _someFactory(someType);
strategy.DoIt();
}
Here is how I did it.
var l = Container.ComponentRegistry.Registrations
.SelectMany(x => x.Services)
.OfType<IServiceWithType>()
.Where(x =>
x.ServiceType.GetInterface(typeof(ISomeInterface).Name) != null)
.Select(c => (ISomeInterface) c.ServiceType);
If you have
container.Register(c => new A()).As<ISomeInterface>();
container.Register(c => new B()).As<ISomeInterface>();
Then when you do
var classes = container.Resolve<IEnumerable<ISomeInterface>>();
You will get a variable that is a list of ISomeInterface, containing A and B
I was looking for a similar solution for registrations done as follows:
builder.RegisterType<Bamboo>().As<IExoticTree>();
// and/or
builder.RegisterType<SolidOak>().Keyed<IMountainTree>(key);
where IExoticTree and IMountainTree inherit from a common ITree interface.
With those, the service type (e.g. registered interface) is different from the LimitType and hence, the proposed solution is not applicable.
I got inspired by the accepted solution to manage these as well with the following code:
IEnumerable<ITree> instances = scope.ComponentRegistry.Registrations
.Where(r => typeof(ITree).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Services.First())
.Select(s => scope.ResolveService(s) as ITree)
.Distinct();
Hope it helps someone ^^
Clarification for any one searching this with regards to Inherited Class
Ex :
public static IEnumerable<Type> GetTypesInherit<T>(this Assembly assembly)
{
var types = assembly.GetTypes()
.Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(T)))
.ToList();
return types;
}
Installer :
public static IContainer Install()
{
var builder = new ContainerBuilder();
var executingAssembly = Assembly.GetExecutingAssembly();
var testScreens = executingAssembly.GetTypesInherit<TestScreen>();
foreach (var testScreen in testScreens)
{
builder.RegisterType(testScreen).As<TestScreen>();
}
var container = builder.Build();
return container;
}
Usage (Implicit) :
public class MainViewModel(IEnumerable<TestScreen> testScreens)
{}
Just tried this, works and does not depend on lifetime context:
Enumerate types using Activator instead
var types = con.ComponentRegistry.Registrations
.Where(r => typeof(ISomeInterface).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Activator.LimitType);
Then to resolve:
IEnumerable<ISomeInterface> lst = types.Select(t => con.Resolve(t) as ISomeInterface);