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
        }
    }
Другие вопросы по тегам