.net 使用Activator示例化模块时,Autofac无法解析模块

new9mtju  于 2023-01-06  发布在  .NET
关注(0)|答案(1)|浏览(159)

我正在尝试使用自定义属性定义希望框架容器加载的外部库中的模块。我能够扫描程序集,查找并验证我的类型,并返回示例化IModule的列表。但是,当我尝试解析在外部模块中注册的类型时,该类型无法解析。
面向.Net标准2.0的主库

public static List<IModule> DiscoverContainerModules()
{
   var modules = new List<IModule>();
   var assemblies = DiscoverAssemblies();

   foreach (var assembly in assemblies)
    {
      modules.AddRange(from type in assembly.GetTypes() 
                    where type.GetCustomAttribute<AppkitModuleAttribute>() != null 
                    where type.IsAssignableTo<IModule>() 
                    select Activator.CreateInstance(type) into module 
                    select module as IModule);
            }
            return modules;
 }

注册模块的扩展方法

public static void UseAppkitModules(this ContainerBuilder builder)
 {
   var modules = AppkitPluginDiscovery.DiscoverContainerModules();

   foreach (var module in modules)
    {
      builder.RegisterModule(module);
    }
 }

从面向.Net Core 6.0的托管应用程序
第一个月
最后是另一个.Net Standard 2.0库中的模块示例

[AppkitModule(nameof(DisplayModule))]
public class DisplayModule : Module
{
  protected override void Load(ContainerBuilder builder)
   {
    builder.Register(c =>
     {
      var conductor = c.Resolve<IConductor>();
      var logger = c.Resolve<ILogger>();

       return new DisplaySubsystem(
          conductor: conductor,
          logger: logger);
       });
     }
 }

如果我简单地更新builder.RegisterModule(new DisplayModule()),这个模块就可以正常工作;我已经确认了Load方法是用我的反射方法调用的。为什么用Activator创建模块示例的行为不同。我还确认了程序集是加载的。
我把模块移到了父库中,同样也失败了;我把所有的扩展方法分解成了一个大的代码块,得到了相同的结果;我甚至用Activator创建了示例,得到了相同的结果。

kgsdhlau

kgsdhlau1#

已解决:

问题的根源是我加载和扫描程序集的方法应用了我的自定义属性。我使用的是Assembly.LoadFile(path)。它似乎没有提供加载我的模块所需的依赖关系。我更新了该方法以使用Assembly.LoadFrom(path),所有模块和类型都能完美地解析。

完整解决方案-加载程序集

private static List<Assembly> LoadReferencedAssemblies()
{
    var assemblies = new List<Assembly>();

    var path = AppContext.BaseDirectory;
    var directory = new DirectoryInfo(path);

    if (!directory.Exists) return assemblies;

    var libraries = directory.GetFiles("*.dll");

    assemblies.AddRange(libraries.Select(fileInfo => Assembly.LoadFrom(fileInfo.FullName)));

    return assemblies;
}

获取具有自定义属性的程序集

private static List<Assembly> DiscoverAssemblies()
{
    var assemblies = new List<Assembly>();
    var attributes = DiscoverAttributes();
    var domain = LoadReferencedAssemblies();

    foreach (var assembly in domain)
    {
        assemblies.AddRange(
            from type in assembly.GetTypes()
            where attributes.Any(attribute => type.GetCustomAttribute(attribute) != null)
            where !assemblies.Contains(assembly)
            select assembly);
    }
    return assemblies;
}

获取具有模块属性的所有类型

public static List<AppkitAssemblyType> DiscoverModules()
{
    var modules = new List<AppkitAssemblyType>();

    modules.AddRange(
        from assembly in AppkitAssemblies
        from type in assembly.GetTypes()
        where type.GetCustomAttribute<AppkitModuleAttribute>() != null
        select new AppkitAssemblyType(type));

    return modules;
}

生成器扩展

public static ContainerBuilder RegisterAppkitModules(this ContainerBuilder builder)
{
     var modules = AppkitPluginDiscovery.DiscoverModules();

      foreach (var module in modules)
      {
           builder.RegisterAssemblyModules(module.Type, module.Assembly);
      }

      return builder;
}

引用程序集中的示例模块

[AppkitModule(nameof(DisplayModule))]
public class DisplayModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<DisplaySubsystem>().AsSelf().SingleInstance();
    }
}

最终容器配置

builder.RegisterAppkitModules()

相关问题