Контракт плагина TinyIoC Resolve

Как можно разрешить контакты плагина с помощью 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>();

контракт IService в Core.Contracts.dll и является ссылкой в ​​хост-сборке, это позволяет плагину перетаскивания работать без перекомпиляции. В EchoCodeAnalysis.dll у нас есть фактическая реализация плагина, которая не упоминается в сборке хоста, но совместно использует хост Core.Contracts.dll с помощью IService.

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", но когда мы просим контейнер разрешить IMenuItem после регистрации EchoMenu в качестве его реализации, мы получаем нуль обратно от разрешить все.

есть идеи?


person Clura.NET    schedule 23.05.2015    source источник
comment
проблема в том, что существует более одной реализации IService, и вы хотите разрешить конкретную одну или все из них?   -  person NeddySpaghetti    schedule 23.05.2015
comment
Их больше одного, но я ожидаю получить один и, в конечном итоге, список, все из которых размещены в одном и том же IService, все классы, похоже, регистрируются с помощью ioc, но не сопоставляются с IService, поэтому при запросе класса IService его неразрешенный , я мог бы запросить класс обслуживания напрямую, если бы на него была только ссылка, и хост знал об этом, но в этом суть plug and play.   -  person Clura.NET    schedule 23.05.2015
comment
Я предполагаю, что регистрация должна каким-то образом дать сбой, вы пытались использовать container.AutoRegister(), то есть без каких-либо параметров?   -  person NeddySpaghetti    schedule 23.05.2015
comment
У меня есть, но авторегистрация будет работать только для текущего домена приложения без параметров, а это означает, что плагин должен быть явно указан при компиляции :/   -  person Clura.NET    schedule 23.05.2015


Ответы (1)


Я нашел способ, не уверенный в передовой практике или потенциальных проблемах с памятью в будущем, с помощью эталонного тестирования.

С использованием:

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);
}

Это может быть неоптимальным, когда вы делаете что-то на лету, поэтому может потребоваться, чтобы менеджер плагинов хранил реализации как экземпляры после запуска приложения и использовал их из списка типов плагинов.

person Clura.NET    schedule 23.05.2015