Unity ResolveAll Универсальный интерфейс
Я использую Unity IoC, я хотел бы зарегистрировать отображение не универсального класса в универсальный интерфейс. После этого я хотел бы использовать метод ResolveAll для получения всей регистрации, связанной с универсальным интерфейсом. Это пример кода:
interface ISample<out T> { }
class Ca : ISample<int> { }
class Cb : ISample<string> { }
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ISample<int>,Ca>();
container.RegisterType<ISample<string>, Cb>();
var classList = container.ResolveAll(typeof(ISample<>));
}
}
в моем коде эта строка:
var classList = container.ResolveAll(typeof(ISample<>));
это ошибка:
Resolution of the dependency failed, type = "ConsoleApplication1Unity.ISample`1[T][]", name = "(none)". Exception occurred while: while resolving. Exception is: InvalidOperationException - Could not execute the method because either the method itself or the containing type is not fully instantiated.
----------------------------------------------- At the time of the exception, the container was:
Resolving ConsoleApplication1Unity.ISample`1[T][],(none)
3 ответа
Я выполнил задачу создания следующего ExtensionMethod
public static IEnumerable<object> ResolveAllOpenGeneric(this IUnityContainer container, Type openGenericType)
{
if (!openGenericType.IsGenericTypeDefinition)
throw new ArgumentNullException("argument must be open generic type");
return container.Registrations.Where(c =>
c.RegisteredType.IsGenericType
&& c.RegisteredType.GetGenericTypeDefinition() == openGenericType
)
.Select(r =>
container.Resolve(r.RegisteredType, r.Name)
);
}
public static IEnumerable<T> ResolveAllOpenGeneric<T>(this IUnityContainer container, Type openGenericType)
{
if (!openGenericType.IsGenericTypeDefinition)
throw new ArgumentNullException("argument must be open generic type");
return container.Registrations.Where(c =>
c.RegisteredType.IsGenericType
&& c.RegisteredType.GetGenericTypeDefinition() == openGenericType
)
.Select(r =>
(T)container.Resolve(r.RegisteredType, r.Name)
);
}
ResolveAll
предназначен для поиска всех именованных разрешений определенного типа, он не работает с открытыми обобщениями, которые вы используете. Чтобы получить то, что вы хотите, вам нужно сделать
var registrations = container.Registrations
.Where(x => x.RegisteredType.IsGenericType &&
x.RegisteredType.GetGenericTypeDefinition() == typeof(ISample<>))
.ToList();
Это даст вам список всех регистраций. Чтобы получить коллекцию объектов класса, вам просто нужно вызвать Resolve
на каждую регистрацию возвращается.
var classList = new List<object>();
foreach (var registration in registrations)
{
var classObject = container.Resolve(registration.RegisteredType, registration.Name);
classList.Add(classObject);
}
Единственный тип List<T>
который может содержать как ISample<int>
а также ISample<string>
является object
, List<ISample<object>>
не будет работать. Если вы переписали интерфейс, чтобы быть
interface ISample { }
interface ISample<out T> : ISample { }
Это делает код намного проще, и вы получаете лучший объект в списке, который позволит вам получить доступ к свойствам и методам ISample
это не зависело от T
,
var registrations = container.Registrations
.Where(x => typeof(ISample).IsAssignableFrom(x.RegisteredType));
var classList = new List<ISample>();
foreach (var registration in registrations)
{
var classObject = container.Resolve(registration.RegisteredType, registration.Name);
classList.Add((ISample)classObject);
}
PS Просто чтобы было понятно, что встроено в ResolveAll
делает, это в основном
public IEnumerable<object> ResolveAll(Type t, params ResolverOverride[] resolverOverrides)
{
var registrations = this.Registrations.Where(x => x.RegisteredType == t);
foreach (var registration in registrations)
{
if(registration.Name != null)
yield return this.Resolve(registration.RegisteredType, registration.Name, resolverOverrides)
}
}
ISample<> не является допустимым типом для Unity; Вы не можете зарегистрировать его и не можете использовать ResolveAll для получения всех типов, использующих его. Если вы посмотрите на то, что ResolveAll возвращает, это поможет показать проблему. В этом случае он вернул бы IEnumerable>, что недопустимо.
Я не совсем уверен, что вы пытаетесь сделать, поэтому я не знаю, что рекомендовать попробовать.