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 インターフェイスをフェッチして解決します。これにより、プラグインはそのインターフェイスに制限され、上位の実装には制限されません。たとえば、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 が返されます。すべてを解決します。

何かご意見は?

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 に答える