首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Funq支持ResolveAll吗?

Funq支持ResolveAll吗?
EN

Stack Overflow用户
提问于 2012-01-12 17:21:32
回答 2查看 1.8K关注 0票数 11

Funq IoC容器支持解析一个类型的所有注册吗?类似于这两个命令之一:

代码语言:javascript
复制
IEnumerable<IFoo> foos = container.Resolve<IEnumerable<IFoo>>();
IEnumerable<IFoo> foos = container.ResolveAll<IFoo>();
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-12 18:27:43

Funq没有ResolveAll方法,但您可以简单地注册一个IEnumerable<IFoo>并使用Resolve<IEnumerable<IFoo>>()解决它,如您在问题中所示。

不过,一般来说,最好不要向容器请求集合,而是使用composites。这样,您就可以简单地将IFoo作为依赖项注入,而不是强迫依赖项的使用者迭代列表。相反,您可以将循环IFoo实例列表的代码嵌入到组合中。当必须更改项目的迭代方式时,这将使您的代码保持DRY,并且不会强迫您遍历散布在整个应用程序中的(可能的)几十个foreach (var foo in foos)语句。或者让我换一种方式说:知道如何迭代所有的IFoo不是消费者的责任。

以下是IFoo组合的示例:

代码语言:javascript
复制
// A composite is something that implements an interface
// (in this case IFoo) and wraps a list of items of that
// same interface.
public class FooComposite : IFoo
{
    private readonly IEnumerable<IFoo> foos;

    public FooComposite(params IFoo[] foos)
    {
        this.foos = foos;
    }

    void IFoo.FooThatThing(IBar bar)
    {
        foreach (var foo in this.foos)
        {
            foo.FooThatThing(bar);
        }
    }
}

您可以将CompositeFoo注册为IFoo,而不是注册IEnumerable<IFoo>

代码语言:javascript
复制
container.Register<IFoo>(c => new CompositeFoo(
    new Foo1(), new Foo2(), new Foo3()));

现在,您可以让容器将该CompositeFoo注入接受IFoo参数的消费者中,这会使它们意识不到自己实际上正在处理一组IFoo元素。

更新

使用此复合模式,您可以轻松地控制每个IFoo项的生命周期。这只是一个回调容器的问题。使用Funq,它看起来像这样:

代码语言:javascript
复制
container.Register<IFoo>(c => new CompositeFoo(
    c.Resolve<Foo1>(),
    c.Resolve<Foo2>(),
    c.Resolve<Foo3>()));

例如,通过这种方式,您可以将Foo1注册为单例,将Foo2注册为瞬态。然而,当CompositeFoo被重用时,Foo2不会真的是暂时的,而只是改变CompositeFoo及其注册来解决这个问题。例如,您可以将CompositeFoo更改为以下内容:

代码语言:javascript
复制
public class FooComposite : IFoo
{
    private readonly Func<IFoo>[] fooFactories;

    public FooComposite(params Func<IFoo>[] fooFactories)
    {
        this.fooFactories = fooFactories;
    }

    void IFoo.FooThatThing(IBar bar)
    {
        foreach (var fooFactory in this.fooFactories)
        {
            var foo = fooFactory();

            foo.FooThatThing(bar);
        }
    }
}

现在,我们可以在构造函数中注入一些IFoo,而不是注入一些lambda:

代码语言:javascript
复制
container.Register<IFoo>(c => new CompositeFoo(
    () => c.Resolve<Foo1>(),
    () => c.Resolve<Foo2>(),
    () => c.Resolve<Foo3>()));

这将确保每次调用CompositeFooFooThatThing时,容器都会查询新的IFoo实例,这使得FooThatThing可以被同一消费者多次调用,甚至可以将CompositeFoo注册为单例。

这个建议通常适用于所有容器和依赖注入,并不特定于Funq的使用。

票数 9
EN

Stack Overflow用户

发布于 2016-06-22 21:25:02

对于那些想要反模式的人来说,仅仅因为你可能不想实现工厂模式,这里是我基于上一版3.9.71的版本。

唯一的缺点是它增加了更多的内存,您必须通过registerOneOfMany()注册服务。您可能希望更改带有锁的列表的包(为了更快地读取),并切换到servicstack funq的默认值:ReuseScope.Default

代码语言:javascript
复制
public static class FunqExtensions
{
    private static readonly ConcurrentDictionary<Type,ConcurrentBag<string>> registrations = new ConcurrentDictionary<Type, ConcurrentBag<string>>();

    public static void RegisterOneOfMany<TBase, TImplementation>(this Container container, string name = null, ReuseScope scope  = ReuseScope.None) where TImplementation : TBase
    {
        if (name == null)
            name = Guid.NewGuid().ToString();

        var funq = Container.GenerateAutoWireFn<TImplementation>();
        container.Register<TBase>(name, (c) => funq(c))
          .ReusedWithin(scope);
        registrations.GetOrAdd(typeof(TBase), type => new ConcurrentBag<string>()).Add(name);
    }

    public static IEnumerable<T> ResolveAll<T>(this Container container)
    {
        ConcurrentBag<string> result;
        if (registrations.TryGetValue(typeof(T), out result))
        {
            var rator = result.GetEnumerator();
            while (rator.MoveNext())
            {
                yield return container.ResolveNamed<T>(rator.Current);
            }
        }
    }  
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8832592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档