[英]TinyIoC Resolve Plugin Contract
如何使用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中,我們具有實際的插件實現,該插件實現在主機程序集中未引用,但使用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從解決所有。
有什么想法嗎?
我通過基准測試找到了一種方法,不確定最佳實踐或將來的潛在內存問題。
使用:
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);
}
動態運行時可能不是最佳選擇,因此一旦啟動應用程序並從插件類型列表中使用它們,可能需要插件管理器將實現作為實例保存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.