【问题标题】:Argument Exception in Dictionary Getter字典 Getter 中的参数异常
【发布时间】:2019-01-10 11:04:15
【问题描述】:

我遇到了一种奇怪的情况,即以特定方式在 C# 字典上使用 getter 会产生参数异常,即使这应该 never happen。这个问题似乎只发生在我的电脑上。

实际上,我已经找到了解决原始问题的替代解决方案。但是我真的很想不明白为什么原来的解决方案不起作用。

我有用于 Solidworks 插件的字典。它跟踪打开的文档及其事件处理程序。它是这样定义的:

private Dictionary<ModelDoc2, DocumentEventHandler> _openDocs = new Dictionary<ModelDoc2, DocumentEventHandler>();

Solidworks 有method 来检索活动文档。当我尝试使用它来检索活动文档的事件处理程序时,如下所示:

_openDocs[SwApp.ActiveDoc]

我得到这个 ArgumentException:

System.ArgumentException: 'Method 'SWAddIn.DocumentEventHandler 
get_Item(SolidWorks.Interop.sldworks.ModelDoc2)' declared on type
'System.Collections.Generic.Dictionary`2[SolidWorks.Interop.sldworks.ModelDoc2,SWAddIn.DocumentEventHandler]' cannot be called with instance of type
'System.Collections.Generic.Dictionary`2[SolidWorks.Interop.sldworks.ModelDoc2,SWAddIn.DocumentEventHandler]''

我发现的替代解决方案是先简单地将活动文档绑定到一个变量,如下所示:

ModelDoc2 activedoc = SwApp.ActiveDoc;
_openDocs[activedoc]

如果有人能帮助我理解那就太好了!

一些额外的信息:

根据文档,“ActiveDoc”应该返回一个“对象”,但智能感知告诉我这是一个动态的

如前所述,它只发生在我的机器上,所以我猜它在某种程度上是环境问题

sn-p 不起作用的代码直接来自 Solidworks 的示例文件。

ModelDoc2 在名为 SolidWorks.Interop.sldworks 的装配体中定义:

[CoClass(typeof(ModelDoc2Class))]
[Guid("B90793FB-EF3D-4B80-A5C4-99959CDB6CEB")]
public interface ModelDoc2 : IModelDoc2

如果感兴趣的话,这里是来自 excpetion 的堆栈跟踪:

   at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method)
   at System.Linq.Expressions.Expression.ValidateAccessor(Expression instance, MethodInfo method, ParameterInfo[] indexes, ReadOnlyCollection`1& arguments)
   at System.Linq.Expressions.Expression.ValidateIndexedProperty(Expression instance, PropertyInfo property, ReadOnlyCollection`1& argList)
   at System.Linq.Expressions.Expression.Property(Expression instance, PropertyInfo indexer, IEnumerable`1 arguments)
   at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateProperty(EXPRCALL pExpr)
   at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Visit(EXPR pExpr)
   at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateLambda(EXPRCALL pExpr)
   at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Visit(EXPR pExpr)
   at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.Rewrite(TypeManager typeManager, EXPR pExpr, IEnumerable`1 listOfParameters)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.CreateExpressionTreeFromResult(IEnumerable`1 parameters, ArgumentObject[] arguments, Scope pScope, EXPR pResult)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
   at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable`1 args, IEnumerable`1 arginfos, DynamicMetaObject onBindingError)
   at Microsoft.CSharp.RuntimeBinder.CSharpGetIndexBinder.FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
   at System.Dynamic.DynamicMetaObject.BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
   at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
   at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at CortimeSWAddIn.SwAddin.OnPostDocChange() in C:\Users\asdf\Development\SWAdd\SWAddIn\SWAddIn\SwAddin.cs:line 1065

【问题讨论】:

  • 这是出乎意料的。如果正确实现 COM 对象,它应该可以工作。您遇到的错误很奇怪,它告诉我们您为该方法提供了一个 System.Collections.Generic.Dictionary`2[SolidWorks.Interop.sldworks.ModelDoc2,SWAddIn.DocumentEventHandler] 的实例。您确定您向我们展示的代码是有错误的真实代码吗? (我没有要测试的软件)
  • 相当肯定。还能在哪里?发生异常的整行代码是检查文档是否已完成加载:if(_openDocs[SwApp.ActiveDoc].Loaded)System.Collections.Generic.Dictionary`2[SolidWorks.Interop.sldworks.ModelDoc2,SWAddIn.DocumentEventHandler] 是字典的类型。我的猜测是此错误消息是由于该方法被实现为扩展。并因此将其作为第一个参数(如果这有意义的话)。
  • 这个异常很奇怪,因为类型相同。你在说什么扩展方法?我们能有真正的代码吗?
  • if(_openDocs[SwApp.ActiveDoc].Loaded) 是真正的代码。也没有太多的上下文。在它之前唯一要做的就是检查活动文档是否为空

标签: c# linq dynamic clr solidworks


【解决方案1】:

每当我看到一个异常说您不能将类型 X 的实例用作类型 X 时,这表明我有多个版本的类型 X 并排加载到内存中。

运行您的程序并查看“模块”窗口,看看是否加载了多个版本的 SolidWorks 库。如果有,那是你的问题。您的代码的一部分将类型 X 解析为版本 A,而期望类型 X 实例的另一部分代码期望版本 B。

您通常可以通过更新所有内容以指向相同版本的库或在 App.config 中使用 assembly binding redirects 来解决此问题。

【讨论】:

  • 奇怪的是几乎没有预期的 dll 出现在模块列表中。我们包含来自solidoworks 的这7 个参考:SolidWorks.Interop.cosworks、SolidWorks.Interop.sldworks、SolidWorks.Interop.swcommands、SolidWorks.Interop.swconst、SolidWorks.Interop.swmotionstudy、SolidWorks.Interop.swpublished 和solidworkstools。但只有最后一个出现在模块列表中。它自己的文档类型应该在 SolidWorks.Interop.sldworks 中
  • 我只是有一个想法。我们可能仅使用互操作程序集进行构建,然后 Solidworks 将其重定向到另一个程序集。听起来对吗?有没有办法找出它被重定向到哪个程序集?
  • 这个答案完全合理。这就像重载一样。也就是说,如果编译器不知道输入的类型是什么,它就无法决定必须使用哪个 _openDocs
  • @Taus 模块窗口应该准确地显示库的哪个版本被加载到内存中以及它从哪里加载。
  • 我觉得很奇怪我没有在模块列表中看到它们。还有其他与 Solidworks 相关的 dll,但不是我链接的那些
【解决方案2】:

您可以尝试转换它,它似乎没有返回正确的类型。声明变量后,它会正确解析和强制转换。

_openDocs[(ModelDoc2)SwApp.ActiveDoc]

【讨论】:

  • 如前所述,我已经找到了几乎就是这样的解决方案。我只是将它分配给一个变量。但是我试图理解为什么它一开始就不起作用。我认为字典应该能够解析类型或至少在编译时警告它不明确/
猜你喜欢
  • 1970-01-01
  • 2012-12-13
  • 2011-01-27
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多