Joe*_*ung 7 c# dependency-injection castle-windsor prism
Can Castle Windsor可以解析由字符串参数过滤的集合吗?
interface IViewFactory
{
IView[] GetAllViewsInRegion(string regionName);
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序将区域定义为IView派生类型的组.当我在运行时显示特定区域时,我想要解析其中每个IView类型的实例(la Prism).
我尝试过使用Castle的Typed Factory Facility,ComponentModel Construction Contributors和Handler Selectors,但是我无法弄清楚如何以Castle可以访问的方式将多个类型映射到字符串,也不知道如何将Castle扩展到在确定要尝试解析哪些类型并在容器中返回时检查字符串.
按字符串选择是否绝对必要?是否可以让同一“区域”中的所有 IView 实现实现从 IView 派生的专用接口?然后,您可以使用 WindsorContainer.ResolveAll()(将特定于区域的 IView 作为 T 传递)来解析相关区域的实现(或者您可以使用集合解析器之一来执行构造函数注入)。
一般来说,当尝试使用 Windsor 执行此类操作时,我会在求助于基于字符串的解决方案之前尽一切努力使用类型系统(以及 Windsor 对它的支持)。
更新:由于我们确认在这种情况下需要通过字符串进行选择,所以我看到的最佳解决方案是简单地检查内核中满足 IView 服务的处理程序列表,然后过滤该区域(通过属性定义)的实现者符合我们想要的,然后解决那些实现者。这感觉有点 hackish,但如果您同意在 IViewFactory 实现中直接引用容器,那么这似乎工作正常。下面是一个通过的测试用例,演示了该解决方案。
[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; }
}
}
Run Code Online (Sandbox Code Playgroud)