¿La selección por cuerda es estrictamente necesaria? ¿Sería posible tener todas las implementaciones IView en la misma "región" implementando una interfaz dedicada que deriva de IView? Entonces podría usar WindsorContainer.ResolveAll() (pasando su IView específica de la región como T) para resolver las implementaciones para la región en cuestión (o podría usar uno de los Resoltores de Colección para realizar la inyección del constructor).
En general, cuando trato de hacer cosas como esta con Windsor, hago todo lo posible por utilizar el sistema tipográfico (y el soporte de Windsor) antes de recurrir a soluciones basadas en cadenas.
Actualización: ya se confirmó que la selección de la cadena es necesario en este caso, la mejor solución que veo es simplemente inspeccionar la lista de controladores en el núcleo, que satisfacen el servicio IView, luego filtrar a los ejecutores en el que el región (definida por atributo) coincide con lo que queremos, luego resuelve esos implementadores. Esto parece un poco hackish, pero si está de acuerdo con tener una referencia directa al contenedor en su implementación de IViewFactory, esto parece funcionar bien. A continuación se muestra un caso de prueba que pasa que demuestra la solución.
[Test]
public void Test()
{
using (var factory = new ViewFactory())
{
var regionOneViews = factory.GetAllViewsInRegion("One");
Assert.That(regionOneViews, Is.Not.Null);
Assert.That(regionOneViews, Has.Length.EqualTo(2));
Assert.That(regionOneViews, Has.Some.TypeOf<RegionOneA>());
Assert.That(regionOneViews, Has.Some.TypeOf<RegionOneB>());
var regionTwoViews = factory.GetAllViewsInRegion("Two");
Assert.That(regionTwoViews, Is.Not.Null);
Assert.That(regionTwoViews, Has.Length.EqualTo(1));
Assert.That(regionTwoViews, Has.Some.TypeOf<RegionTwoA>());
}
}
}
public interface IViewFactory
{
IView[] GetAllViewsInRegion(string regionName);
}
public class ViewFactory : IViewFactory, IDisposable
{
private readonly WindsorContainer _container;
public ViewFactory()
{
_container = new WindsorContainer();
_container.Register(
Component.For<IView>().ImplementedBy<RegionOneA>(),
Component.For<IView>().ImplementedBy<RegionOneB>(),
Component.For<IView>().ImplementedBy<RegionTwoA>()
);
}
public IView[] GetAllViewsInRegion(string regionName)
{
return _container.Kernel.GetHandlers(typeof (IView))
.Where(h => IsInRegion(h.ComponentModel.Implementation, regionName))
.Select(h => _container.Kernel.Resolve(h.ComponentModel.Name, typeof (IView)) as IView)
.ToArray();
}
private bool IsInRegion(Type implementation,
string regionName)
{
var attr =
implementation.GetCustomAttributes(typeof (RegionAttribute), false).SingleOrDefault() as RegionAttribute;
return attr != null && attr.Name == regionName;
}
public void Dispose()
{
_container.Dispose();
}
}
public interface IView {}
[Region("One")]
public class RegionOneA : IView {}
[Region("One")]
public class RegionOneB : IView {}
[Region("Two")]
public class RegionTwoA : IView {}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RegionAttribute : Attribute
{
private readonly string _name;
public RegionAttribute(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
}
}
intento utilizar tipos en lugar de claves de cadena, también, pero el punto de extensión Prism Estoy trabajando con (RegionBehavior) asocia las regiones con las cadenas, por lo que no se puede ver ninguna manera alrededor de la selección por la cadena. En realidad, Prism solo espera objetos en la región, por lo que incluso la interfaz IView es una simplificación artificial de mi parte. En [revisión 1] (http://stackoverflow.com/revisions/9394391/1) di un montón de contexto para mi pregunta, pero creo que estaba asustando a la gente. –
Algunas regiones se definen en complementos. Las cosas se vuelven muy complicadas y lentas si mi clase tiene que buscar conjuntos cargados para una interfaz de marcador con el nombre corto '" I "+ regionName +" View "'. Preferiría decorar clases con un atributo personalizado como 'ViewExport [RegionName =" MainRegion "]' y tipos de filtro en algo como el punto de extensión HandlersFilter de Windsor. –
Bien, entiendo, no estoy familiarizado con Prism, así que no me di cuenta de que la selección de la secuencia era necesaria. Creo que algo como esto debería ser posible. Trataré de encontrar algo en mi tiempo libre hoy :-) –