unity ResolveAll 泛型接口
Unity ResolveAll Generics Interface
我正在使用 Unity IoC,我想注册非通用 class 到通用接口的映射。之后,我想使用 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)
ISample<> 不是 Unity 的有效类型;您无法注册它,也无法使用 ResolveAll 来获取所有使用它的类型。如果您查看 ResolveAll returns,这有助于说明问题。在这种情况下,它将 return 一个无效的 IEnumerable>。
我不太确定你想做什么,所以我不知道推荐尝试什么。
ResolveAll
用于查找特定类型的所有命名解析,它不适用于您正在使用的开放泛型。要得到你想要的,你需要做
var registrations = container.Registrations
.Where(x => x.RegisteredType.IsGenericType &&
x.RegisteredType.GetGenericTypeDefinition() == typeof(ISample<>))
.ToList();
这将为您提供所有注册的列表。要获取 class 对象的集合,您只需在每次返回的注册时调用 Resolve
。
var classList = new List<object>();
foreach (var registration in registrations)
{
var classObject = container.Resolve(registration.RegisteredType, registration.Name);
classList.Add(classObject);
}
唯一可以同时容纳 ISample<int>
和 ISample<string>
的 List<T>
类型是 object
。 List<ISample<object>>
是行不通的。如果您将界面重写为
interface ISample { }
interface ISample<out T> : ISample { }
它使代码更简单,并且您在列表中得到一个更好的对象,它可以让您访问不依赖于 T
.[=25 的 ISample
的属性和方法=]
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);
}
P.S. 只是为了弄清楚内置的 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)
}
}
我已经完成创建以下 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)
);
}
我正在使用 Unity IoC,我想注册非通用 class 到通用接口的映射。之后,我想使用 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)
ISample<> 不是 Unity 的有效类型;您无法注册它,也无法使用 ResolveAll 来获取所有使用它的类型。如果您查看 ResolveAll returns,这有助于说明问题。在这种情况下,它将 return 一个无效的 IEnumerable>。
我不太确定你想做什么,所以我不知道推荐尝试什么。
ResolveAll
用于查找特定类型的所有命名解析,它不适用于您正在使用的开放泛型。要得到你想要的,你需要做
var registrations = container.Registrations
.Where(x => x.RegisteredType.IsGenericType &&
x.RegisteredType.GetGenericTypeDefinition() == typeof(ISample<>))
.ToList();
这将为您提供所有注册的列表。要获取 class 对象的集合,您只需在每次返回的注册时调用 Resolve
。
var classList = new List<object>();
foreach (var registration in registrations)
{
var classObject = container.Resolve(registration.RegisteredType, registration.Name);
classList.Add(classObject);
}
唯一可以同时容纳 ISample<int>
和 ISample<string>
的 List<T>
类型是 object
。 List<ISample<object>>
是行不通的。如果您将界面重写为
interface ISample { }
interface ISample<out T> : ISample { }
它使代码更简单,并且您在列表中得到一个更好的对象,它可以让您访问不依赖于 T
.[=25 的 ISample
的属性和方法=]
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);
}
P.S. 只是为了弄清楚内置的 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)
}
}
我已经完成创建以下 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)
);
}