如何使用筛选参数解析集合

本文关键字:集合 参数 何使用 筛选 | 更新日期: 2023-09-27 18:25:29

Castle Windsor可以解析由字符串参数过滤的集合吗?

interface IViewFactory
{
   IView[] GetAllViewsInRegion(string regionName);
}

我的应用程序将区域定义为IView派生类型的组。当我在运行时显示一个特定的区域时,我想解析其中每个IView类型的实例(一个la Prism)。

我已经尝试过使用Castle的Typed Factory Facility、ComponentModel Construction Contributors和Handler Selectors来实现这一点,但我不知道如何以Castle可以访问的方式将多个类型映射到一个字符串,也不知道如何在Castle决定要解析并返回容器中的类型时扩展Castle来检查字符串。

如何使用筛选参数解析集合

是否严格需要通过字符串进行选择?是否可以让同一"区域"中的所有IView实现实现一个从IView派生的专用接口?然后,您可以使用WindsorContainer.RevolveAll()(将特定于区域的IView传递为T)来解析有问题的区域的实现(或者您可以使用其中一个集合解析器来执行构造函数注入)。

一般来说,当我尝试用Windsor做这样的事情时,在求助于基于字符串的解决方案之前,我会尽一切努力使用类型系统(以及Windsor对其的支持)。

更新:由于我们确认在这种情况下需要按字符串进行选择,我看到的最佳解决方案是简单地检查内核中满足IView服务的处理程序列表,然后筛选区域(通过属性定义)与我们想要的相匹配的实现程序,然后解析这些实现程序。这感觉有点麻烦,但如果您可以在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; }
    }
}