Autofac: зарегистрировать типы конструкторов плагинов во время выполнения
Я работаю над модульным приложением, в котором плагины автоматически загружаются при запуске. Плагины работают, однако, вместо того, чтобы требовать от плагинов создания своих собственных объектов в конструкторе, я хочу сделать это автоматически с помощью автофактора и отражения. Следующий код работает, но мне интересно, есть ли у Autofac способ сделать это проще. Вот фрагмент кода:
foreach (var module in modulesAssemblies)
{
try
{
var constructors =
module.DefinedTypes.First(k => k.Name == module.GetName().Name + "ViewModel")
.GetConstructors()[0];
if (constructors == null) continue;
foreach (var param in constructors.GetParameters())
{
if (param.ParameterType.Name.StartsWith("I"))
{
var type = param.ParameterType;
var officalType =
module.DefinedTypes.Where(k => type.IsAssignableFrom(k) && k.Name != type.Name)
.Select(k => k);
builder.RegisterType(officalType.First()).As(type).AsImplementedInterfaces();
}
}
}
catch { }
}
Я использую Caliburn.Micro (отсюда + "ViewModel"). Плагины загружаются в модули Assemblies. Они уже загружены через AssemblySource.Instance. Я не буду знать, какие плагины содержат конструкторы, поэтому я не могу предварительно собрать их, так как все будет динамично.
Есть ли более простой способ сделать это?
1 ответ
Вот решение, которое я выбрал. Оно работает:
private static void RegisterAssemblyInterfaces(List<Assembly> modulesAssemblies, ContainerBuilder builder)
{
var baseType = typeof (IPluginView);
var pluginAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => baseType.IsAssignableFrom(p) && baseType != p);
foreach (var assembly in pluginAssemblies)
{
var module = modulesAssemblies.FirstOrDefault(k => k.GetTypes().Any(v => v.IsAssignableFrom(assembly)));
if (module == null) continue;
var types = module.DefinedTypes.ToList();
var interfaces = module.GetTypes().Where(k => k.IsInterface).ToList();
if (!interfaces.Any()) continue;
RegisterInterfaceToTypes(builder, interfaces, types);
}
}
private static void RegisterInterfaceToTypes(ContainerBuilder builder, List<Type> interfaces, List<TypeInfo> types)
{
try
{
foreach (var @interface in interfaces)
foreach (var type in types.Where(type => @interface.IsAssignableFrom(type) && @interface != type))
builder.RegisterType(type).As(@interface).AsImplementedInterfaces();
}
catch
{
// ignored
}
}