2011-05-30 30 views
2

我的.net程序正在使用程序集,该程序集应安装在GAC中。提前验证是否可以找到程序集

如果组件安装正确,它会在我第一次使用时立即加载,这很好。例如,如果我使用类似如下的程序集:

ESRI::ArcGIS::esriSystem::AoInitialize^ aoi = gcnew ESRI::ArcGIS::esriSystem::AoInitializeClass(); 

程序集将被加载。

现在有时候程序集不会出现在GAC中,我需要程序注意到这一点但不会崩溃。

我试过包装组件的使用到这样的try/catch块:

try 
{ 
    ESRI::ArcGIS::esriSystem::AoInitialize^ aoi = gcnew ESRI::ArcGIS::esriSystem::AoInitializeClass(); 
} 
catch (System::Exception^) 
{ 
    // assembly not found 
} 

但程序不会抛出异常,但崩溃来代替。

如何预先检查装配是否在GAC中,并且可以在不碰撞的情况下使用?或者我怎样才能捕捉崩溃并禁用我的程序中相应的菜单项?

+0

可能的重复:http://stackoverflow.com/questions/1933947/check-gac-for-an-assembly – 2011-05-30 13:46:30

+0

在等待编辑:这不是C#,这是托管-C++!我会编辑它,但在拒绝按钮上单击得太快而不是编辑它... – Stormenet 2011-05-30 13:56:28

回答

2

您有关于程序集,装载的方式错了心智模式。它在组件中创建类型的实例时发生而不是。 JIT编译器是首先需要程序集的编译器。为该方法生成机器码。如果您查看该例外的调用堆栈,则会看到在调用方法中引发了异常。

至少,这是您使用Microsoft Jitter时通常会发生的情况,它会在最后时刻按需生成机器代码。对于其他的烦躁不安,比如单声道,它更热切地编译。

你可以在调用方法中捕获异常,但这很脆弱。除了抖动依赖性之外,您还必须使用[MethodImpl(MethodImplOptions.NoInlining)]将该方法赋予属性,以确保此代码不会被内联。因为这将再次导致该类型需要太快。

正确的修复方法是使用插件体系结构。您必须使用接口类型来声明您想要在主程序中使用的属性和方法。该接口类型需要在单独的程序集中声明,并由主程序和插件引用。并与您的主程序一起部署,无论您的客户是否可以使用插件选项。使用Assembly.Load()来加载插件程序集和Assembly.CreateInstance()来创建实现该接口的类型的具体实例。并且永远不要在代码中引用具体类型,只涉及接口类型。你会发现很多谷歌查询的例子。

+0

感谢关于jit的解释,它解释了很多!所以你的建议是使用插件中的第三方程序集,所以当我尝试加载插件时会出现错误,因此不知道使用这个函数? – Sam 2011-06-01 12:36:44

+0

呃,不知道这听起来是对的。关键点是“永远不要在代码中引用具体类型”,其他所有内容都遵循这一点。 – 2011-06-01 12:43:18

+0

嗯,我无法改变第三方dll或他们的安装,所以我不能将它们改成插件。因此,如果我想遵循您的建议,我需要使用插件作为包装。 – Sam 2011-06-01 13:02:41

0

最好的方法是在安装过程中添加所有必要的组件。

但是,在创建类型之前,可以通过简单的类型检查来实现您想要的功能。

事情是这样的:

var t = System.Type.GetType("TypeName, Assembly"); 
if (t == null) throw CannotLoadTypeException(); 
+0

客户不想为每个工作站购买组件,所以当它不存在时,我需要禁用使用它的功能。盗版DLL并安装它们不是一种选择。 – Sam 2011-05-30 14:25:55

+0

我试图使用这个,但我总是得到nullptr作为结果,即使当程序集存在。我使用System :: Type^t = System :: Type :: GetType(“ESRI.ArcGIS.esriSystem.AoInitializeClass,ESRI.ArcGIS.System”); – Sam 2011-05-30 14:35:20

+0

尝试完整的程序集名称。 – 2011-05-30 16:27:29

相关问题