字典获取器中的参数异常

10
我遇到了一个奇怪的情况,在特定的方式下使用C#字典的getter方法会引发参数异常,尽管这 永远不应该 发生。这个问题似乎只在我的电脑上发生。
实际上,我已经找到了一个替代工作的解决方案来解决我的原始问题。但是我真的很想知道为什么原始解决方案不起作用。
我有一个用于Solidworks插件的字典,它跟踪打开的文档及其事件处理程序。它的定义如下:
private Dictionary<ModelDoc2, DocumentEventHandler> _openDocs = new Dictionary<ModelDoc2, DocumentEventHandler>();

Solidworks有方法可以检索活动文档。当我尝试使用它来检索活动文档的事件处理程序时,就像这样:
_openDocs[SwApp.ActiveDoc]

我遇到了这个参数异常:
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”应该返回一个“对象”,但是智能感知告诉我它是动态的。
如上所述,这仅发生在我的机器上,因此我猜测它在某种程度上是环境性的。
无法正常工作的代码片段直接来自于Solidworks示例文件。
ModelDoc2在名为SolidWorks.Interop.sldworks的程序集中定义,并具有以下定义:
[CoClass(typeof(ModelDoc2Class))]
[Guid("B90793FB-EF3D-4B80-A5C4-99959CDB6CEB")]
public interface ModelDoc2 : IModelDoc2

如果有兴趣,这里是异常的堆栈跟踪:

   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]`实例传递给方法。你确定你展示给我们的代码是真正有错误的代码吗?(我没有SW来测试) - Simon Mourier
相当确定。还能在哪里呢?发生异常的整行代码是检查文档是否已经加载完成:if(_openDocs[SwApp.ActiveDoc].Loaded)System.Collections.Generic.Dictionary\2[SolidWorks.Interop.sldworks.ModelDoc2,SWAddIn.DocumentEventHandler]` 是字典的类型。我猜测这个错误信息是由于该方法被实现为扩展方法,因此将其作为第一个参数(如果有意义的话)。 - Taus
这个异常很奇怪,因为类型是相同的。你在谈论哪个扩展方法?我们能看到真正的代码吗? - Simon Mourier
if(_openDocs[SwApp.ActiveDoc].Loaded) 是这段真实的代码。没有太多上下文信息。它之前唯一的检查是查看活动文档是否为空。 - Taus
2个回答

4
每当我看到一个异常,说不能将类型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中。 - Taus
我突然想到了一件事。我们可能只是使用Interop程序集进行编译,然后Solidworks将其重定向到另一个程序集。这听起来正确吗?有没有办法找出它被重定向到哪个程序集? - Taus
这个答案是完全合理的。这就像重载一样。也就是说,如果编译器不知道输入的类型是什么,它无法决定使用哪个_openDocs。 - Aida
@Taus 你关心的是定义了名为ModelDoc2的类的那些程序集。它可能在多个程序集中定义。 - Dan
那将是SolidWorks.Interop.sldworks。至少当我使用“转到定义”时,我会被带到那里。我已经在帖子中编辑了它的定义。 - Taus
显示剩余2条评论

0
你可以尝试进行强制类型转换,似乎它没有返回正确的类型。一旦你声明了变量,它就会正确地解析和转换。
_openDocs[(ModelDoc2)SwApp.ActiveDoc]

1
如前所述,我已经找到了解决方案,就是将其分配给一个变量。然而,我正在尝试理解为什么一开始它没有起作用。我认为字典应该能够解析类型,或者至少在编译时警告它是模糊的。 - Taus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接