简体   繁体   中英

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

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.

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...

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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM