1

如何使用 TinyIoC 解决插件联系人?

Host.exe /w 对 Core.Contract.dll 的引用

var container = new TinyIoCContainer();
container.AutoRegister(new[] { Assembly.LoadFrom("Core.Contracts.dll") }, 
                DuplicateImplementationActions.RegisterMultiple);
container.AutoRegister(new[] { Assembly.LoadFrom("EchoCodeAnalysis.dll") }, 
                DuplicateImplementationActions.RegisterMultiple);
var mi = container.Resolve<IService>();

Core.Contracts.dll 中的合同 IService 并在主机程序集中引用,这是为了让拖放插件有机会在不重新编译的情况下工作。在 EchoCodeAnalysis.dll 中,我们有实际的插件实现,它没有在主机程序集中引用,但使用 IService 共享 Core.Contracts.dll 的主机。

Core.Contract.dll:

public interface IService
{
    string ID { get; set; }
}

EchoCodeAnalysis.dll:

public class Service : IService
{
    string IService.ID
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

编辑:

我设法解决了问题的第一部分。

var type = typeof(IService);
var types = (new[] { Assembly.LoadFrom("EchoCodeAnalysis.dll") }).ToList()
                .SelectMany(s => s.GetTypes())
                .Where(x => type.IsAssignableFrom(x) && x.IsClass).ToList();

container.RegisterMultiple<IService>(types.ToArray());

var mi = container.ResolveAll<Core.Contracts.IService>();

将获取并解析所有 IService 接口,这将插件限制为该接口,而不是任何高级实现。比如说,IMenuItem 实现为 IService,上面的代码可以找到任何可以追溯到 IService 起源的类,但是那些显式实现 IMenuItem 的类可以说名称,当解析为 IService 时,它​​只会获取 IService 属性而不包括IMenuItem 属性。那是在哪里。container.Register(types.ToArray()).AsRespectiveImplementations() 会派上用场。但是这个问题有什么地方吗?或者这是一个必须编写来扩展 TinyIOC 的实用程序?

编辑2:

然后我们搬到了一个扩展,但我们仍然没有得到任何解决。

    public static IEnumerable<T> GetPluginsForModule<T>()
    {
        var type = typeof(T);
        var types = Plugins.SelectMany(s => s.GetTypes())
            .Where(x => type.IsAssignableFrom(x) && x.IsClass).ToList();
        foreach (var t in types)
        {
            if (t.CustomAttributes.Where(x => x.AttributeType == typeof(CluraPlugin)).Any()) 
            {
                CustomAttributeData attr = t.CustomAttributes.Where(x => x.AttributeType == typeof(CluraPlugin)).FirstOrDefault();
                if (attr == null)
                    break;

                string Name = attr.ConstructorArguments.Where(x => x.ArgumentType == typeof(string)).FirstOrDefault().Value as string;
                Type InterfaceTypeArgument = attr.ConstructorArguments.Where(x => x.ArgumentType == typeof(Type)).FirstOrDefault().Value as Type;

                Container.Register(InterfaceTypeArgument, t, Name).AsMultiInstance();
            }
        }
        return Container.ResolveAll(type) as IEnumerable<T>;
    }

我传递了正确的值,在上面的 Container.Register 中,我们有 InterfaceTypeArgument = IMenuItem, t = EchoMenu : IMenuItem, Name = "EchoMenu" 但是当我们要求容器在注册 EchoMenu 作为其实现后解析 IMenuItem 时,我们会返回 null从解决所有。

有什么想法吗?

4

1 回答 1

0

我找到了一种方法,不确定未来的最佳实践或潜在的内存问题,通过基准测试。

使用:

string PluginDirectory = Directory.GetCurrentDirectory() +"\\Plugins\\";
PluginManager.LoadDirectory(PluginDirectory);
var mi = PluginManager.GetPluginsForModule<IService>();

这解决了这样的事情:

public static IEnumerable<object> GetPluginsForModule<T>()
{
    var type = typeof(T);
    var types = Plugins.SelectMany(s => s.GetTypes())
            .Where(x => type.IsAssignableFrom(x) && x.IsClass).ToList();
    foreach (var t in types)
    {
        if (t.CustomAttributes.Where(x => x.AttributeType == typeof(CluraPlugin)).Any()) 
        {
           CustomAttributeData attr = t.CustomAttributes.Where(x => x.AttributeType == typeof(CluraPlugin)).FirstOrDefault();
           if (attr == null)
              break;

           string Name = attr.ConstructorArguments.Where(x => x.ArgumentType == typeof(string)).FirstOrDefault().Value as string;
           Type InterfaceTypeArgument = attr.ConstructorArguments.Where(x => x.ArgumentType == typeof(Type)).FirstOrDefault().Value as Type;

           Container.Register(InterfaceTypeArgument, t, Name).AsMultiInstance();
         }
     }
     return Container.ResolveAll(type);
}

在动态执行操作时它可能不是最佳的,因此一旦您启动应用程序并从插件类型列表中使用它们,可能需要插件管理器将实现作为实例保存。

于 2015-05-23T21:13:03.280 回答