Autofac:在运行时注册插件构造函数类型

时间:2016-03-17 20:21:54

标签: c# plugins module autofac caliburn

我正在开发一个模块化应用程序,其中插件会在启动时自动加载。但是,插件工作,而不是要求插件在构造函数中实例化自己的对象,我想通过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加载。我不知道插件包含什么构造函数,所以我不能预先构建它们,因为它们都是动态的。

有更简单的方法吗?

1 个答案:

答案 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
        }
    }