c# - 如何解析带有过滤参数的集合?

标签 c# dependency-injection castle-windsor prism

CaSTLe Windsor 能否解析由字符串参数过滤的集合?

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

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

我已经尝试使用 CaSTLe 的类型化工厂设施、ComponentModel Construction Contributors 和 Handler Selectors 来实现它,但我不知道如何以 CaSTLe 可以访问的方式将多个类型映射到一个字符串,也不知道如何扩展 CaSTLe 以在它决定尝试在容器中解析和返回哪些类型时检查字符串。

最佳答案

按字符串选择是否绝对必要?是否可以让同一“区域”中的所有 IView 实现实现一个派生自 IView 的专用接口(interface)?然后您可以使用 WindsorContainer.ResolveAll()(将特定于区域的 IView 作为 T 传递)来解析相关区域的实现(或者您可以使用其中一个 Collection Resolver 来执行构造函数注入(inject))。

一般来说,当尝试用 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; }
    }
}

关于c# - 如何解析带有过滤参数的集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9394391/

相关文章:

NHibernate (3.1.0.4000) NullReferenceException 使用 Query<> 和 NHibernate Facility

c# - 在 C# 中实现 JS Eval

用于编译时的 Scala 依赖注入(inject),具有单独的配置

asp.net-mvc - 没有为此对象定义无参数构造函数。注入(inject) + MVC 5

asp.net-mvc-3 - ASP.NET MVC3 - 使用 DependencyResolver 和温莎城堡 : Why?

c# - 温莎城堡 : How to retrieve proxy for specific instance?

c# - Visual Studio 2010 Professional 播放按钮已禁用

c# - 什么时候在实例类中使用私有(private)静态方法有意义

javascript - 在 Web 应用程序中使用 Readium

javascript - 无法使用 AngularJS 显式 `$http` 语法注入(inject) `app.controller`?