разрешить все заданные типы


Из документации Autofac я вижу, как получить все регистрации для класса T:

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

Но когда у меня есть только доступный тип, как я могу получить эквивалентные результаты?

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

Я пытаюсь реализовать класс-оболочку, который имеет предварительно определенный интерфейс.


EDIT

Для краткости ответ от Мэтью Уотсона (с соответствующими идеями от Дэвида Л.):

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

2 ответа:

Вот вам пример. Я добавил утверждения, чтобы доказать, что типы, возвращаемые из 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);
}
Таким образом, два должны быть эквивалентными, поскольку они реализуются таким образом.

Вы можете вызвать _container.Разрешите проблему, вызвав обернутый метод через reflection (MSDN), но при этом вы потеряете безопасность типа во время компиляции.

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[] { });
    } 
}