對於版本,您可能需要爲每個版本的接口adapter pattern它們之間去。這就是System.AddIn
如何處理版本控制,它也適用於MEF。
比方說,我們有以下幾種類型的應用程序的V1:
public interface IPlugin
{
string Name { get; }
string Publisher { get; }
string Version { get; }
void Init();
}
這是我們V1插件感知應用程序的唯一合同。它包含在程序集Contracts.v1
中。
然後我們有一個V1插件:
[Export(typeof(IPlugin))]
public class SomePlugin : IPlugin
{
public string Name { get { return "Some Plugin"; } }
public string Publisher { get { return "Publisher A"; } }
public string Version { get { return "1.0.0.0"; } }
public void Init() { }
public override string ToString()
{
return string.Format("{0} v.{1} from {2}", Name, Version, Publisher);
}
}
這是導出爲IPlugin
。它包含在程序集Plugin.v1
中,併發布在主機的應用程序基路徑下的「插件」文件夾中。
最後V1主持人:
class Host : IDisposable
{
CompositionContainer _container;
[ImportMany(typeof(IPlugin))]
public IEnumerable<IPlugin> Plugins { get; private set; }
public Host()
{
var catalog = new DirectoryCatalog("plugins");
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
public void Dispose() { _container.Dispose(); }
}
其中進口文件夾 「插件」 中找到的所有IPlugin
部分。
然後,我們決定出版V2因爲我們希望提供的版本,我們將需要versionless合同:
public interface IPluginV2
{
string Name { get; }
string Publisher { get; }
string Version { get; }
string Description { get; }
void Init(IHost host);
}
一個新的屬性和方法的方法簽名。此外,我們增加一個接口主機:
public interface IHost
{
//Here we can add something useful for a plugin.
}
上述這些問題都包含在裝配Contracts.v2
。
要允許版本我們添加一個插件適配器從V1到V2:
class V1toV2PluginAdapter : IPluginV2
{
IPlugin _plugin;
public string Name { get { return _plugin.Name; } }
public string Publisher { get { return _plugin.Publisher; } }
public string Version { get { return _plugin.Version; } }
public string Description { get { return "No description"; } }
public V1toV2PluginAdapter(IPlugin plugin)
{
if (plugin == null) throw new ArgumentNullException("plugin");
_plugin = plugin;
}
public void Init(IHost host) { plugin.Init(); }
public override string ToString() { return _plugin.ToString(); }
}
這只是適應從IPlugin
到IPluginV2
。它返回一個固定的描述,並在Init
中對主機參數不做任何處理,但它從合同中調用無參數Init
。
最後的V2主持人:
class HostV2WithVersioning : IHost, IDisposable
{
CompositionContainer _container;
[ImportMany(typeof(IPluginV2))]
IEnumerable<IPluginV2> _pluginsV2;
[ImportMany(typeof(IPlugin))]
IEnumerable<IPlugin> _pluginsV1;
public IEnumerable<IPluginV2> Plugins
{
get
{
return _pluginsV1.Select(p1 => new V1toV2PluginAdapter(p1)).Concat(_pluginsV2);
}
}
public HostV2WithVersioning()
{
var catalog = new DirectoryCatalog("plugins");
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
public void Dispose() { _container.Dispose(); }
}
其中進口都IPlugin
和IPluginV2
部分,以適應每個IPlugin
到IPluginV2
,並公開所有發現的插件連接序列。適應完成後,所有插件都可以視爲V2插件。
您也可以使用主機的接口適配器模式允許V2插件與V1主機配合使用。
另一種方法是autofac IoC,它可以與MEF配合使用integrate,並且可以使用adapters支持版本控制。