I am working with an API called ArcObjects and .NET 4.5. I encountered the error
'object' does not contain a definition for 'AddValue'
while using one of the objects on the API, but I think this may be a more general .NET issue than one with this API. This is an error that occurs at runtime.
For some background, ArcObjects are all COM objects so the .NET libraries are just wrappers around those. When working with ArcObjects I am primarily working with a Geodatabase which is basicaly a regular RDBS (with a spatial component) where each row is called a feature.
My first attempt code was as follows:
//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);
The definition for AddValue is AddValue(string,string,ISymbol)
. This compiles without an error or warning and AddValue can be found via Reflection at runtime.
I was able to get around this issue by changing my last line to the following:
string value = SampleAreaFeature.get_Value(idIndex).ToString();
uvRenderer.AddValue(value, "SampleField", redSymbol as ISymbol);
Even stranger the following does NOT work:
var value = SampleAreaFeature.get_Value(idIndex).ToString();
uvRenderer.AddValue(value, "SampleField", redSymbol as ISymbol);
And this brings me to the issue at hand. Why are these three snippets compiling differently?
A value that is not explicitly typed is producing different results, both of which compile, but one of which cannot bind to the AddValue method at runtime.
Here is the IL for when the 'var' keyword is used:
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
And here is the IL for when the 'string' keyword is used:
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)