当类位于另一个命名空间中时编组 .NET 对象
我在 .NET Windows 服务中跨应用程序域编组对象时遇到问题。
我创建了两个应用程序,它们跨应用程序域编组对象并通过代理 MarshalByRefObject
运行代码。
第一个应用程序是一个简单的概念证明,因为我在跨应用程序域编组方面没有很多经验。它包含一个项目,其中 MarshalByRefObject
与项目的其余部分在同一命名空间中定义。这个应用程序运行良好,使用与我的其他应用程序几乎相同的代码。主要区别在于,我在第二个应用程序中编组的类是在另一个命名空间中定义的。
另一个项目更复杂,它是一个具有多个项目的Windows Service。主 Windows 服务加载一个执行编组操作的库。 Marshal 目标类型的类类型是在另一个库中定义的,因此我使用完全限定的命名空间/类名。
我面临的问题是,当它到达下面代码的最后一行时,它会抛出异常:
无法从程序集 ProductNameService 中加载 CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler 其中产品名称是主要的 Windows 服务类。
代码:
AppDomain compilerDomain = null;
AppDomainSetup compilerDomainSetup;
CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler scriptCompiler;
...
// Setup a seperate AppDomain
compilerDomainSetup = new AppDomainSetup();
exeAssembly = Assembly.GetEntryAssembly().FullName;
compilerDomainSetup.ApplicationBase = System.Environment.CurrentDirectory;
compilerDomainSetup.DisallowBindingRedirects = false;
compilerDomainSetup.DisallowCodeDownload = true;
compilerDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
compilerDomain = AppDomain.CreateDomain("LiveLinkCSScriptDomain", null, compilerDomainSetup);
// Create an instance of the MarshalByRefScriptCompiler in the other AppDomain
scriptCompiler = (CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler)compilerDomain.CreateInstanceAndUnwrap(exeAssembly, typeof(CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler).FullName);
我已经对此异常进行了研究,几乎所有我发现的内容都表明这是 DLL 版本控制的问题,但是我的 DLL 不在 GAC 中,并且没有安装其他版本。我正在做一个干净的构建并使用 installutil 安装服务。
我使用 MSDN 文档 作为创建代码的指南 我想知道
加载 MarshalByRefScriptCompiler
是否存在问题,因为该类型位于另一个库中。我可以在一个简单的 winforms 应用程序中创建一个 MarshalByRefScriptCompiler
,但我在 Windows 服务中遇到异常。
任何提示或见解将不胜感激!
I am having a problem with Marshalling an object across application domains in a .NET Windows Service.
I have created two app's that marshal an object across an app domain and run code through a proxy MarshalByRefObject
The first application was a simple proof of concept since I do not have a lot of experience with marshalling across application domains. It contains a single project where the MarshalByRefObject
is defined in the same namespace as the rest of the project. This app works fine, using almost the same code as my other app. The main difference is that the class I am Marshalling in the second app is defined in another Namespace.
The other project is more complex, it is a Windows Service with multiple projects. The main Windows Service loads a library that that does the marshalling. The class type of the Marshal target type is defined in another library, so I use the fully qualified namespace/class name.
The problem I am facing is that when it gets to the last line of the code below it throws an exception:
Could not load CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler from assembly ProductNameService where product name is the main Windows Service class.
The Code:
AppDomain compilerDomain = null;
AppDomainSetup compilerDomainSetup;
CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler scriptCompiler;
...
// Setup a seperate AppDomain
compilerDomainSetup = new AppDomainSetup();
exeAssembly = Assembly.GetEntryAssembly().FullName;
compilerDomainSetup.ApplicationBase = System.Environment.CurrentDirectory;
compilerDomainSetup.DisallowBindingRedirects = false;
compilerDomainSetup.DisallowCodeDownload = true;
compilerDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
compilerDomain = AppDomain.CreateDomain("LiveLinkCSScriptDomain", null, compilerDomainSetup);
// Create an instance of the MarshalByRefScriptCompiler in the other AppDomain
scriptCompiler = (CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler)compilerDomain.CreateInstanceAndUnwrap(exeAssembly, typeof(CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler).FullName);
I have done research on this exception and almost everything I find says that it is a problem with versioning of the DLL, however my DLL's are not in the GAC, and there are no other versions installed. I am doing a clean build and installing the service with installutil.
I used the MSDN documentation as a guide for creating the code that does the marshalling
I am wondering if there is an issue with loading the MarshalByRefScriptCompiler
because the type is in another library. I am able to create a MarshalByRefScriptCompiler
in a simple winforms app, but I get the exception in my windows service.
Any tips or insight would be greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我应该能够帮助你。我最近花了很多时间(我如何通过引用作为跨应用程序域的方法参数?)致力于解决不同的跨应用程序域封送问题。我的第一个建议是尝试使用 CreateInstanceFromAndUnwrap 而不是 CreateInstanceAndUnwrap。
我也对这一行有点警惕:
你原来的 AppDomain 是如何创建的?您是否托管在 IIS 中,在这种情况下您的原始 AppDomain 将使用 ShadowCopy?所有 dll 都包含在一个文件夹中吗?
编辑:
总而言之,如果您的 compilerDomainSetup.ApplicationBase 设置为包含 dll 的目录并且传入正确的第一个参数(例如 typeof(MarshalByRefScriptCompiler)),则可以使用 CreateInstanceAndUnwrap .Assembly.FullName)。
或者,您可以使用 CreateInstanceFromAndUnwrap 并仅传入包含程序集的位置(例如 typeof(MarshalByRefScriptCompiler).Assembly.Location)作为第一个参数。
I should be able to help you. I've spent many hours recently (How do I pass references as method parameters across AppDomains?) working on different cross appdomain marshaling problems. My first suggestion would be to try using CreateInstanceFromAndUnwrap instead of CreateInstanceAndUnwrap.
I'm also a little wary of this line:
How is your original AppDomain being created? Are you hosted in IIS, in which case your original AppDomain will be using ShadowCopy? Are all the dlls involved in a single folder?
EDIT:
To summarize, you can use CreateInstanceAndUnwrap if your compilerDomainSetup.ApplicationBase is set to the directory containing your dll and you pass in the correct first param (e.g. typeof(MarshalByRefScriptCompiler).Assembly.FullName).
Or, you can use CreateInstanceFromAndUnwrap and just pass in the location (e.g. typeof(MarshalByRefScriptCompiler).Assembly.Location) of the containing assembly as the first param.
作为起点,您可以尝试进程监视器来确定它尝试加载的位置您缺少的类型。这很可能就像在错误的目录中查找程序集一样简单。
As a starting point, you could try Process Monitor to determine where it's trying to load your missing type from. It's very possible that it's as simple as it looking in the wrong directory for your assembly.