C# Unity ResolveAll和解析未注册的类型

C# Unity ResolveAll和解析未注册的类型,c#,unity-container,C#,Unity Container,简单问题;对于未注册的类型,是否可以解析所有 在理想情况下,我会有一个类似于IPluggable接口的接口,解析后将返回继承该接口的对象集合 // both unregistered types public class PluginOne : IPluggable { } public class PluginTwo : IPluggable { } // returns instances of PluginOne and PluginTwo IEnumerable<IPluggab

简单问题;对于未注册的类型,是否可以解析所有

在理想情况下,我会有一个类似于
IPluggable
接口的接口,解析后将返回继承该接口的对象集合

// both unregistered types
public class PluginOne : IPluggable { }
public class PluginTwo : IPluggable { }

// returns instances of PluginOne and PluginTwo
IEnumerable<IPluggable> result = container.ResolveAll<IPluggable>
//两种未注册的类型
公共类PluginOne:IPluggable{}
公共类PluginTwo:IPluggable{}
//返回PluginOne和PluginTwo的实例
IEnumerable结果=container.ResolveAll

据我所知,使用StructureMap等替代方案是可以实现的,但遗憾的是,我们的结构是围绕统一构建的。我能想到的唯一解决方案是创建一个引导程序,使用一点反射和名称空间挖掘来自动注册某些类型?

是的,你是对的。Unity不会解析任何未注册的类型(除非您要求类的单个实例而不是接口)。建议的解决方案——bootstrapper——是我在许多项目中成功使用的解决方案。我遇到的唯一问题是选择要扫描的DLL列表,如果您希望它在文件夹中找到扩展名,这可能会很棘手。最节省的方法是为此添加一个配置部分。

有一个与Structure Map的配置引擎非常相似的配置部分


它允许您扫描程序集以查找接口的实现,并支持自定义约定。

我创建了自己的扩展,该扩展基于我的接口IBlock解析类型。扩展只在正在执行的程序集中查找,但可能会在您想要的任何地方查找。从这一点上,应该可以做一个扩展来满足您的需求

伊布洛克:

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;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用Microsoft.Practices.Unity;
公共类UnityBlockRegistrationXtender:UnityContainerExtension
{
私有只读名称类型映射名称类型映射=新名称类型映射();
受保护的覆盖无效初始化()
{
var blockType=typeof(IBlock);
var blockTypes=Assembly.GetEntryAssembly().GetTypes()
其中(block=>blockType.IsAssignableFrom(block)和&block.IsClass);
foreach(blockTypes中的变量类型)
{
if(this.nameToTypesMap.AddType(type.AssemblyQualifiedName,type))
{
var block=this.Container.Resolve(type)为IBlock;
块寄存器(这个容器);
}
}
}
私有类名称类型映射
{
私有只读字典映射=新字典();
内部bool AddType(字符串名称、类型)
{
if(name==null)
{
抛出新ArgumentNullException(“名称”,“需要名称”);
}
if(type==null)
{
抛出新ArgumentNullException(“类型”,“需要类型对象”);
}
锁(此.map)
{
如果(!this.map.ContainsKey(名称))
{
this.map[name]=类型;
返回true;
}
}
返回false;
}
}
}

稍加调整,我就能找到正确的答案。关键区别;我正在扫描执行程序集文件路径中的所有程序集。谢谢@Wietze。