c# - MEF plugin calling another plugin with same interface -


i trying make (my first mef) system in plugins can recursive, i.e. main system calls mef plugin standard interface, on own can call (or several) plugin(s), , on.

when testing though, plugin not call underlying plugin, starts processing (creating loop).

any idea how can prevent this?

interface:

public interface iconnector {     xdocument run(object servicecredentials, object connectorids, object connectorkeys); } 

my main plugin inherits interface, , defines import next (the subplugin has same definition):

[export(typeof(iconnector))] public class connector : iconnector {     [import(typeof(iconnector))]     private iconnector connector;     .... 

the called plugin initiated (in run method of main plugin):

public xdocument run(object servicecredentials, object connectorids, object connectorkeys) {     string calledconnector = path.combine(assemblydirectory, "subplugin.dll");     assemblycatalog assembycatalog = new assemblycatalog(assembly.loadfrom(calledconnector));     compositioncontainer container = new compositioncontainer(assembycatalog);     container.composeparts(this);     .... 

the container should contain 1 plugin, subplugin.dll. call method 'run' in interface invoke subplugin method:

xdocument = connector.run(servicecredentials, connectorids, connectorkeys); 

but, instead of running subplugin code, 'run' method in main plugin activates, keeps activating itself.

when remove [export(typeof(iconnector)] in main plugin, subplugin activated, want main plugin able called in same manner.

being new mef stuck how solve this. appreciated!

you should use contracts , specify intent, otherwise mef go infinite loop or pick connector exposes iconnector itself.

some more info msdn.

for example

[export("container", typeof(iconnector))] public class connector : iconnector {     [import("component", typeof(iconnector))]     private iconnector connector;     .... 

update

so after giving thought, here example of metadata based approach, , 1 limits number of expensive catalog operations.

the iconnector

using system.xml.linq;  namespace common {     public interface iconnector     {         xdocument run(object servicecredentials, object connectorids, object connectorkeys);          void identify();     } } 

the metadata attribute connectormetadata

using system; using system.collections.generic; using system.componentmodel.composition;  namespace common {     [metadataattribute]     [attributeusage(attributetargets.class)]     public class connectormetadata : exportattribute     {         public string name { get; private set; }          public connectormetadata(string name):base(typeof(iconnector))         {             name = name;         }          public connectormetadata(idictionary<string, object> metadata) : base(typeof (iconnector))         {             name = convert.tostring(metadata["name"]);         }     } } 

the lazy singleton pluginscatalog

using system; using system.componentmodel.composition; using system.componentmodel.composition.hosting; using system.io; using system.linq; using system.reflection; using common;  namespace common {     public class pluginscatalog     {         [importmany]         public lazy<iconnector, connectormetadata>[] connectors;          private static readonly lazy<pluginscatalog> lazyinstance = new lazy<pluginscatalog>(() => new pluginscatalog());          private pluginscatalog()         {             var assemblycatalog = new assemblycatalog(assembly.getexecutingassembly());              var path = path.getdirectoryname(assembly.getexecutingassembly().location) ?? directory.getcurrentdirectory();             var directorycatalog = new directorycatalog(path, "*plugin.dll");              var aggregatecatalog = new aggregatecatalog(assemblycatalog, directorycatalog);              var container = new compositioncontainer(aggregatecatalog);             container.satisfyimportsonce(this);         }          public static pluginscatalog instance { { return lazyinstance.value; } }          public iconnector getconnector(string name)         {             var match = connectors.singleordefault(s => s.metadata.name.equals(name));             return match == null ? null : match.value;         }     } } 

the "primary" iconnector

using system; using system.xml.linq; using common;  namespace common {     [connectormetadata("primary")]     public class connector : iconnector     {          public xdocument run(object servicecredentials, object connectorids, object connectorkeys)         {             pluginscatalog.instance.getconnector("sub").identify();             return default(xdocument);         }          public void identify()         {             console.writeline(gettype().fullname);         }      } } 

the "sub" iconnector

using system; using system.xml.linq; using common;  namespace subplugin {     [connectormetadata("sub")]     public class subconnector:iconnector     {         public xdocument run(object servicecredentials, object connectorids, object connectorkeys)         {             return default(xdocument);         }          public void identify()         {             console.writeline(gettype().fullname);         }     } } 

and program itself:

namespace somef {     class program     {          static void main(string[] args)         {             var connector = pluginscatalog.instance.getconnector("primary");             connector.identify();             connector.run(null, null, null);         }     } } 

which prints:

somef.connector subplugin.subconnector 

hope helps ... :)


Comments

Popular posts from this blog

html - Firefox flex bug applied to buttons? -

html - Missing border-right in select on Firefox -

c# - two queries in same method -