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 インターフェイスをフェッチして解決します。これにより、プラグインはそのインターフェイスに制限され、上位の実装には制限されません。たとえば、IService として実装された IMenuItem の場合、上記のコードは、IService の起源にさかのぼる任意のクラスを見つけることができますが、IService として解決されると、IService プロパティのみをフェッチし、含まれない IMenuItem を明示的に実装するクラスを見つけることができます。 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 が返されます。すべてを解決します。
何かご意見は?