将依赖关系解析程序与 autofac wcf 集成结合使用

using Dependency resolver with autofac wcf integration

提问人:user1542652 提问时间:11/7/2023 更新时间:11/8/2023 访问量:42

问:

我正在处理一个 wcf 项目并使用 autofac 并且它正在工作。 但是,我的要求是,我将此服务部署在不同的系统上,并且它需要使用这些系统上存在的程序集。 例如,我的 wcf 使用 Assembly1 和 Assembly2,我可以在我的 PC 上的项目中引用这些程序集并构建服务,并且运行良好。

但是,这些程序集在将部署 wcf 的不同系统上具有不同的版本。因此,我不能只使用 wcf 服务来交付我的程序集。我已经在我首先在autofac中注册的类的构造函数之一中配置了下面的AssemblyResolver,并尝试从我复制这些程序集的不同路径加载Assembly1和Assembly2,并尝试通过Assembly.LoadFrom加载它。

AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;

但是,当我从 PostBuildEvent 的 wcf bin 文件夹中删除 Assembly1 和 Assembly2 并认为 ResolveAssembly 应该在提供的文件夹中查找这些程序集时。但它不会尝试使用 ResolveAssembly 事件处理程序加载程序集。Wcf 服务在以下行失败,指出它找不到 Assembly1 或 Assembly2。

AutofacHostFactory.Container = container;
C# WCF 自动法克

评论


答:

1赞 Terentiy Gatsukov 11/7/2023 #1

看起来您遇到的问题是,在事件有机会处理这些程序集的缺失之前,可能会加载程序集。如果用于安装的代码已引用这些程序集中的示例,则可能会发生这种情况。.NETAssemblyResolveAssemblyResolve

您需要确保在应用程序启动后立即订阅该事件,然后再尝试查找任何这些外部程序集。这意味着在方法的开头或应用程序的入口点进行设置。AssemblyResolveMain

它可能如下所示:

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

    // Other startup code can go here
}

确保使用应用程序预期的程序集的确切版本不会给应用程序带来任何意外。如果每个部署中的版本都不同,则可能不希望引用项目中的特定版本。

其他一些提示:

  1. 密切关注以检查程序集绑定是否跳闸。程序集绑定日志查看器Fusion Log Viewer (fuslogvw.exe)
  2. 确保您的容器知道分数,并在动态装配体加载准备好摇摆后进行设置。Autofac
0赞 QI You 11/8/2023 #2

我建议你重写ResolveAssembly方法。

public static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        try
        {
            
            string assemblyPath = Path.Combine(DynamoPathManager.Instance.MainExecPath, new AssemblyName(args.Name).Name + ".dll");
            if (File.Exists(assemblyPath))
            {
                return Assembly.LoadFrom(assemblyPath);
            }

            
            foreach (var addPath in DynamoPathManager.Instance.AdditionalResolutionPaths)
            {
                assemblyPath = Path.Combine(addPath, new AssemblyName(args.Name).Name + ".dll");
                if (File.Exists(assemblyPath))
                {
                    return Assembly.LoadFrom(assemblyPath);
                }
            }

            return null;
        }
        catch (Exception ex)
        {
            throw new Exception(string.Format("{0} could not be resolved for loading.", args.Name), ex);
        }
    }