Неявная типизация.NET вызывает исключение RuntimeBinder

Я работаю с API под названием ArcObjects и.NET 4.5. Я столкнулся с ошибкой

'object' does not contain a definition for 'AddValue'

при использовании одного из объектов API, но я думаю, что это может быть более общей проблемой.NET, чем с этим API. Это ошибка, которая возникает во время выполнения.

Для некоторого фона все объекты ArcObject являются COM-объектами, поэтому библиотеки.NET являются просто обертками вокруг них. При работе с ArcObjects я в основном работаю с базой геоданных, которая в основном представляет собой обычную RDBS (с пространственным компонентом), где каждая строка называется объектом.

Моя первая попытка кода была следующей:

//this IUniqueValueRenderer is an ArcObject
var uvRenderer = new ESRI.ArcGIS.Carto.UniqueValueRendererClass() as IUniqueValueRenderer;

//...   set some parameters on the uvRenderer

//the error occurs on this line. SampleAreaFeature.get_Value(idIndex) returns the non-null integer 324
//SampleAreaFeature is a feature in the geodatabase
uvRenderer.AddValue(SampleAreaFeature.get_Value(1).ToString(), "SampleField", redSymbol as ISymbol);

Определение для AddValue является AddValue(string,string,ISymbol), Он компилируется без ошибок и предупреждений, и AddValue можно найти через Reflection во время выполнения.

Я смог обойти эту проблему, изменив мою последнюю строку следующим образом:

string value = SampleAreaFeature.get_Value(idIndex).ToString();
uvRenderer.AddValue(value, "SampleField", redSymbol as ISymbol);

Даже незнакомец следующее НЕ работает:

var value = SampleAreaFeature.get_Value(idIndex).ToString();
uvRenderer.AddValue(value, "SampleField", redSymbol as ISymbol);

И это подводит меня к проблеме. Почему эти три фрагмента собираются по-разному?

Значение, которое не указано явно, дает разные результаты, которые компилируются, но один из которых не может быть привязан к методу AddValue во время выполнения.

Вот IL для использования ключевого слова var:

IL_00bb: call class ESRI.ArcGIS.Geodatabase.IFeature DataReviewModule.ModGlobals::get_SampleAreaFeature()
IL_00c0: ldloc.2
IL_00c1: callvirt instance object ESRI.ArcGIS.Geodatabase.IFeature::get_Value(int32)
IL_00c6: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, object>::Invoke(!0, !1)
IL_00cb: stloc.3
IL_00cc: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`5<class [System.Core]System.Runtime.CompilerServices.CallSite, class [ESRI.ArcGIS.Carto]ESRI.ArcGIS.Carto.IUniqueValueRenderer, object, string, class ESRI.ArcGIS.Display.ISymbol>> DataReviewModule.docWinReview/'<>o__127'::'<>p__1'
IL_00d1: brtrue.s IL_0125

IL_00d3: ldc.i4 256
IL_00d8: ldstr "AddValue"
IL_00dd: ldnull
IL_00de: ldtoken DataReviewModule.docWinReview
IL_00e3: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_00e8: ldc.i4.4
IL_00e9: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
IL_00ee: dup
IL_00ef: ldc.i4.0
IL_00f0: ldc.i4.1
IL_00f1: ldnull
IL_00f2: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)
IL_00f7: stelem.ref

А вот IL для использования ключевого слова 'string':

IL_00f5: call class ESRI.ArcGIS.Geodatabase.IFeature DataReviewModule.ModGlobals::get_SampleAreaFeature()
IL_00fa: ldloc.2
IL_00fb: callvirt instance object ESRI.ArcGIS.Geodatabase.IFeature::get_Value(int32)
IL_0100: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, object>::Invoke(!0, !1)
IL_0105: callvirt instance !2 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, string>::Invoke(!0, !1)
IL_010a: stloc.3
IL_010b: ldloc.1
IL_010c: ldloc.3
IL_010d: ldsfld string DataReviewModule.ModGlobals::sampleIdField
IL_0112: ldarg.0
IL_0113: ldfld class ESRI.ArcGIS.Display.ISimpleFillSymbol DataReviewModule.docWinReview::redSymbol
IL_0118: isinst ESRI.ArcGIS.Display.ISymbol
IL_011d: callvirt instance void [ESRI.ArcGIS.Carto]ESRI.ArcGIS.Carto.IUniqueValueRenderer::AddValue(string, string, class ESRI.ArcGIS.Display.ISymbol)

1 ответ

SampleAreaFeature.get_Value(idIndex) вернул динамику.

Это приводит к var value быть типом dynamic,

Есть какое-то правило о привязке COM, которое я не понимаю, что вызывает два определения AddValue бороться здесь, что не приводит к динамическому разрешению. Разрешение COM-имен объединяет все интерфейсы для поиска имен, что избавило меня от неприятностей, но, похоже, у вас проблемы.

Также вполне возможно, что этот класс не поддерживает динамический вызов во время выполнения. Отражение выполняется для видимого типа, а динамический вызов - для реального типа. Если они не совпадают, происходят странные вещи, и у меня есть код, который зависит от них, чтобы работать вокруг интерфейса COM. Guid, который дублировался (один пользователь - MS-Word, и я не знаю, кто другой). Если реальный тип не поддерживает динамическое разрешение, это будет ожидаемой ошибкой.

Лично я бы порекомендовал исправить это ((object)SampleAreaFeature.get_Value(idIndex)).ToString() таким образом заставляя.ToString() разрешать напрямую, а не через dynamic,

Другие вопросы по тегам