結合IoC容器這樣做,如簡單噴油器的優點在於它是很容易的共同邏輯添加到所有的插件。我最近寫了一個批量圖像轉換工具,允許插入新的圖像轉換器。
這是接口
public interface IImageConverter : IDisposable
{
string Name { get; }
string DefaultSourceFileExtension { get; }
string DefaultTargetFileExtension { get; }
string[] SourceFileExtensions { get; }
string[] TargetFileExtensions { get; }
void Convert(ImageDetail image);
}
註冊像這樣做(注意錯誤檢查的插件依賴不在.NET程序集)的所有插件需要
private void RegisterImageConverters(Container container)
{
var pluginAssemblies = this.LoadAssemblies(this.settings.PluginDirectory);
var pluginTypes =
from dll in pluginAssemblies
from type in dll.GetExportedTypes()
where typeof(IImageConverter).IsAssignableFrom(type)
where !type.IsAbstract
where !type.IsGenericTypeDefinition
select type;
container.RegisterAll<IImageConverter>(pluginTypes);
}
private IEnumerable<Assembly> LoadAssemblies(string folder)
{
IEnumerable<string> dlls =
from file in new DirectoryInfo(folder).GetFiles()
where file.Extension == ".dll"
select file.FullName;
IList<Assembly> assemblies = new List<Assembly>();
foreach (string dll in dlls) {
try {
assemblies.Add(Assembly.LoadFile(dll));
}
catch { }
}
return assemblies;
}
通用邏輯-in操作由裝飾者處理
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterChecksumDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterDeleteAndRecycleDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterUpdateDatabaseDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterLoggingDecorator));
該最後一類更具體b UT我將它作爲你如何能找到所需要的插件爲例,無需將容器
public sealed class PluginManager : IPluginManager
{
private readonly IEnumerable<IImageConverter> converters;
public PluginManager(IEnumerable<IImageConverter> converters) {
this.converters = converters;
}
public IList<IImageConverter> List() {
return this.converters.ToList();
}
public IList<IImageConverter> FindBySource(string extension) {
IEnumerable<IImageConverter> converters = this.converters
.Where(x =>
x.SourceFileExtensions.Contains(extension));
return converters.ToList();
}
public IList<IImageConverter> FindByTarget(string extension) {
IEnumerable<IImageConverter> converters = this.converters
.Where(x =>
x.TargetFileExtensions.Contains(extension));
return converters.ToList();
}
public IList<IImageConverter> Find(
string sourceFileExtension,
string targetFileExtension)
{
IEnumerable<IImageConverter> converter = this.converters
.Where(x =>
x.SourceFileExtensions.Contains(sourceFileExtension) &&
x.TargetFileExtensions.Contains(targetFileExtension));
return converter.ToList();
}
public IImageConverter Find(string name) {
IEnumerable<IImageConverter> converter = this.converters
.Where(x => x.Name == name);
return converter.SingleOrDefault();
}
}
的直接依賴您註冊在容器IPluginManager
和簡單的注射器沒有休息:
container.Register<IPluginManager, PluginManager>();
我希望這有助於。
此問題僅限於Simple Injector? – aevitas
您是否閱讀過[本維基頁面](https://simpleinjector.codeplex.com/wikipage?title=Advanced-scenarios#Plugins)?我認爲它更接近你想要實現的目標。 – Steven
@aevitas不,我在開發階段的這個時候使用Simple Injector,但如果您對另一個DI/IOC工具很容易實現這一點有任何建議,請隨時提及它們。我是DI/IOC初學者,所以我對任何事情都很開放。 – tjeuten