разрешить все заданные типы
Из документации 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 ответа:
Вот вам пример. Я добавил утверждения, чтобы доказать, что типы, возвращаемые из
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[] { }); } }