简单的问题;对于未注册的类型,是否可以ResolveAll<T>
?
在一个理想的世界中,我会有一个类似于IPluggable
接口的东西,当它被解析时会返回一个继承该接口的对象集合。
// both unregistered types
public class PluginOne : IPluggable { }
public class PluginTwo : IPluggable { }
// returns instances of PluginOne and PluginTwo
IEnumerable<IPluggable> result = container.ResolveAll<IPluggable>
据我所知,它可以通过StructureMap等替代方案实现,但遗憾的是我们的结构是围绕Unity构建的。我能想到的唯一解决方案是创建一个引导程序,使用一些反射和命名空间挖掘自动注册某些类型?
答案 0 :(得分:2)
是的,你是对的。 Unity不会解析任何未注册的类型(除非你要求单个类的实例而不是接口)。提出的解决方案 - bootstrapper - 是我在许多项目中成功使用的解决方案。我唯一的问题是选择要扫描的dll列表,如果你想让它在你的文件夹中找到扩展名,这可能会很棘手。最省钱的方法是为此添加配置部分。
答案 1 :(得分:1)
我创建了自己的扩展,根据我的界面IBlock解析了类型。扩展只在执行程序集中查找,但可能会在您想要的任何地方查找。从这里可以做出你想要的扩展。
I块:
using Microsoft.Practices.Unity;
public interface IBlock
{
void Register(IUnityContainer unity);
}
扩展:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Practices.Unity;
public class UnityBlockRegistrationExtender : UnityContainerExtension
{
private readonly NameToTypesMap nameToTypesMap = new NameToTypesMap();
protected override void Initialize()
{
var blockType = typeof(IBlock);
var blockTypes = Assembly.GetEntryAssembly().GetTypes()
.Where(block => blockType.IsAssignableFrom(block) && block.IsClass);
foreach (var type in blockTypes)
{
if (this.nameToTypesMap.AddType(type.AssemblyQualifiedName, type))
{
var block = this.Container.Resolve(type) as IBlock;
block.Register(this.Container);
}
}
}
private class NameToTypesMap
{
private readonly Dictionary<string, Type> map = new Dictionary<string, Type>();
internal bool AddType(string name, Type type)
{
if (name == null)
{
throw new ArgumentNullException("name", "A name is required.");
}
if (type == null)
{
throw new ArgumentNullException("type", "A Type object is required.");
}
lock (this.map)
{
if (!this.map.ContainsKey(name))
{
this.map[name] = type;
return true;
}
}
return false;
}
}
}
答案 2 :(得分:0)
有一个extension for Unity与Structure Map的配置引擎非常相似。
它允许您扫描程序集以实现接口,并且还支持自定义约定。