How do I populate a MEF plugin with data that is not hard coded into the assembly?

匿名 (未验证) 提交于 2019-12-03 01:00:01

问题:

I am working on a program that will communicate with various pieces of hardware. Because of the varied nature of the items it communicates and controls, I need to have a different "driver" for each different piece of hardware. This made me think that MEF would be a great way to make those drivers as plugins that can be added even after the product has been released.

I've looked at a lot of examples of how to use MEF, but the question that I haven't been able to find an answer to is how to populate a MEF plugin with external data (eg. from a database). All the examples I can find have the "data" hard-coded into the assembly, like the following example:

[Export( typeof( IRule ) )]   public class RuleInstance : IRule   {     public void DoIt() {}        public string Name       {           get { return "Rule Instance 3"; }       }      public string Version       {           get { return "1.1.0.0"; }       }        public string Description       {           get { return "Some Rule Instance"; }       }   }

What if I want Name, Version and Description to come from a database? How would I tell MEF where to get that information?

I may be missing something very obvious, but I don't know what it is.

回答1:

You would have to either pass the information to the plugin after it loaded via properties:

[Export( typeof( IRule ) )]   public class RuleInstance : IRule   {     puliic void DoIt()      { }      public string Name { get; set; } }  public class Program {     [Import(typeof( IRule ))]     public IRule instance { get; set; }      public void Run()     {         // Load the assemblies here          instance.Name = "Rule Instance 3";     }              }

Or the plugin could request the variables though a host interface. You can either pass the IHost instance through a property or though a constructor parameter, but constructor parameters are not simple with MEF. Here is through a property:

 [Export( typeof( IRule ) )]   public class RuleInstance : IRule   {     puliic void DoIt()      { }      public void Initialise()     {         // Load our name from the host, this cannot be done in the constructor         string name = Host.GetName(/* some parameters? */)     }       public IHost Host { get; set; }     public string Name { get; set; } }  public interface IHost {     string GetName(/* some parameters? */); }  public class Program : IHost {     [Import(typeof( IRule ))]     public IRule instance { get; set; }      public void Run()     {         // Load the assemblies here                 // Make sure the plugins know where the host is...         instance.Host = this;     }              }

You could also "Export" the database interface and "Import" it into any plugins that need database access...



回答2:

You can always export individual values (through contract names), here's an example:

public class Configuration {   [Export("SomeValue")]   public string SomeValue   {     get { /* return value from database perhaps? */ }   } }  [Export(typeof(IRule))] public class RuleInstance : IRule {   [Import("SomeValue")]   public string SomeValue { get; private set; } }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!