解决所有给定的类型

时间:2014-12-03 15:58:16

标签: autofac

Autofac documentation我可以看到如何获得T类的所有注册:

public T[] ResolveAll<T>()
{
  return _container.Resolve<IEnumerable<T>>().ToArray();
}

但是当我只有Type可用时,我怎样才能获得相同的结果?

public Array ResolveAll(Type service)
{
  return _container.Resolve( ??? 
}

我正在尝试实现一个具有预定义接口的包装器类。


修改

为了快速参考,Matthew Watson的回答(来自David L的相关想法)是:

public Array ResolveAll(Type service)
{
    var typeToResolve = typeof(IEnumerable<>).MakeGenericType(service);
    return _container.Resolve(typeToResolve) as Array;    
}

2 个答案:

答案 0 :(得分:1)

这是一个例子。我添加了断言来证明从ResolveAll<T>(this IContainer self)返回的类型与从ResolveAll(this IContainer self, Type type)返回的类型相同(并且顺序相同):

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Autofac;
using Autofac.Core;

namespace AutofacTrial
{
    public abstract class Base
    {
        public abstract string Name { get; }

        public override string ToString()
        {
            return Name;
        }
    }

    public sealed class Derived1: Base
    {
        public override string Name
        {
            get
            {
                return "Derived1";
            }
        }
    }

    public sealed class Derived2: Base
    {
        public override string Name
        {
            get
            {
                return "Derived2";
            }
        }
    }

    public sealed class Derived3: Base
    {
        public override string Name
        {
            get
            {
                return "Derived3";
            }
        }
    }

    static class Program
    {
        static void Main()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<Derived1>().As<Base>();
            builder.RegisterType<Derived2>().As<Base>();
            builder.RegisterType<Derived3>().As<Base>();

            var container = builder.Build();

            var array1 = container.ResolveAll(typeof(Base));
            var array2 = container.ResolveAll<Base>();

            Trace.Assert(array1.Length == 3);
            Trace.Assert(array2.Length == 3);

            for (int i = 0; i < array1.Length; ++i)
            {
                Trace.Assert(array1[i].GetType() == array2[i].GetType());
                Console.WriteLine(array1[i]);
            }
        }

        public static T[] ResolveAll<T>(this IContainer self)
        {
            return self.Resolve<IEnumerable<T>>().ToArray();
        }

        public static object[] ResolveAll(this IContainer self, Type type)
        {
            Type enumerableOfType = typeof(IEnumerable<>).MakeGenericType(type);
            return (object[]) self.ResolveService(new TypedService(enumerableOfType));
        }
    }
}

基础实施相同

我还使用Reflector来查看Resolve<IEnumerable<T>>()的实现,最后这样做了:

public static TService Resolve<TService>(this IComponentContext context, IEnumerable<Parameter> parameters)
{
    return (TService) context.Resolve(typeof(TService), parameters);
}

调用:

public static object Resolve(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters)
{
    return context.ResolveService(new TypedService(serviceType), parameters);
}

所以两个必须是等价的,因为它们是以这种方式实现的。

答案 1 :(得分:1)

您可以通过反射(MSDN)调用包装方法来调用_container.Resolve,但这样做会失去编译时类型的安全性。

public class Container
{
    public T[] ResolveAll<T>()
    {
        return _container.Resolve<IEnumerable<T>>().ToArray();
    }

    public object ResolveAllGeneric(Type t)
    {
        MethodInfo method = GetType().GetMethod("ResolveAll")
                             .MakeGenericMethod(new Type[] { t });
        return method.Invoke(this, new object[] { });
    } 
}