我正在开发一个模块化应用程序,其中插件会在启动时自动加载。但是,插件工作,而不是要求插件在构造函数中实例化自己的对象,我想通过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”)。插件加载在modulesAssemblies中。它们已经通过AssemblySource.Instance加载。我不知道插件包含什么构造函数,所以我不能预先构建它们,因为它们都是动态的。
有更简单的方法吗?
答案 0 :(得分:0)
这是我采用的解决方案。它有效:
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
}
}