使用IoC容器(如Simple Injector)与此相结合的优点在于,可以轻松地向所有插件添加通用逻辑。我最近编写了一个批量图像转换工具,允许插入新的图像转换器。
这是接口:
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;
}
所有插件操作所需的常规逻辑由装饰器处理。
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterChecksumDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterDeleteAndRecycleDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterUpdateDatabaseDecorator));
container.RegisterDecorator(
typeof(IImageConverter),
typeof(ImageConverterLoggingDecorator));
这个最终的类更具体,但我将其添加为一个示例,展示如何在不直接依赖于容器的情况下找到所需的插件。
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
,Simple Injector 将处理其余内容:
container.Register<IPluginManager, PluginManager>()
我希望这能帮到您。