.NET 6动态调用类库多次调用Web服务遇类型转换异常如何解决?
解决.NET 6动态调用类库时Web服务代理类型转换异常问题
问题场景
基于.NET 6开发的类库用于调用第三方Web服务,由.NET 6 Web应用动态调用。首次调用Web服务可正常获取响应,但第二次调用时抛出异常:
System.InvalidCastException: Unable to cast object of type 'generatedProxy_2' to type 'ServiceReference.FileServiceType'
直接调用类库无此问题,但业务场景必须使用动态调用。
核心原因
动态调用时若每次加载类库都创建新的AssemblyLoadContext,会导致同一类型(如FileServiceType)被加载到不同的上下文,CLR会将它们视为完全不同的类型;同时WCF代理生成机制在不同加载上下文下会生成不同的代理类(如generatedProxy_2),进一步引发类型不匹配。
解决方案
1. 复用AssemblyLoadContext
不要每次动态调用都创建新的加载上下文,复用同一个AssemblyLoadContext加载目标类库,确保所有类型处于同一上下文:
// 全局单例的AssemblyLoadContext,避免重复创建 private static readonly AssemblyLoadContext _sharedLoadContext = new AssemblyLoadContext("WebServiceLibContext", isCollectible: false); public void LoadAndInvokeLibrary() { var assemblyPath = "path/to/your/classlibrary.dll"; // 复用同一上下文加载程序集 var assembly = _sharedLoadContext.LoadFromAssemblyPath(assemblyPath); // 后续创建实例、调用方法的逻辑 }
2. 统一WCF代理生成规则
针对WCF服务引用场景,通过配置显式指定共享代理类型,避免每次调用生成新的代理类:
在Web应用的appsettings.json中添加WCF配置:
{ "system.serviceModel": { "client": { "endpoint": { "name": "FileServiceType", "binding": "basicHttpBinding", "contract": "ServiceReference.IFileService", "address": "http://thirdparty/service-address" } } } }
创建WCF客户端时显式指定已知类型,确保代理类型一致:
var client = new FileServiceClient(); client.Endpoint.Behaviors.Add(new DataContractSerializerOperationBehavior(client.Endpoint.Contract) { KnownTypes = { typeof(ServiceReference.FileServiceType) } });
3. 为类库添加强命名
为类库添加强命名,确保动态加载时CLR识别为同一程序集,避免因加载路径或版本差异导致的类型隔离:
- 打开类库项目属性,勾选“签名”选项,创建并关联强命名密钥文件
- 重新编译类库,确保动态加载的是强命名后的程序集
4. 缓存已加载的类型
避免每次调用都重新加载程序集,缓存已加载的类型实例:
// 缓存已加载的服务客户端类型 private static Type _serviceClientType; public void InvokeWebService() { if (_serviceClientType == null) { var assembly = _sharedLoadContext.LoadFromAssemblyPath(assemblyPath); _serviceClientType = assembly.GetType("YourNamespace.ServiceClient"); } var client = Activator.CreateInstance(_serviceClientType); // 调用服务方法的逻辑 }
内容的提问来源于stack exchange,提问作者Dhara Vaghasiya
相关产品推荐
相关产品推荐

