Today I was working on a project in VB.NET, which I had to convert to C#.
The problem was that they used late binding, they knew that some properties on objects existed, but they couldn’t be deduced by the compiler since the object’s type was Object.
For Example, let’s say we want to get the workbook of a chart.
A chart resides in a ChartObject (the chart.Parent) and a ChartObject resides in a Worksheet.
So chart.Parent.Parent returns the corresponding worksheet.
Like this:
Option Strict Off
Imports Microsoft.VisualBasic
Public Class TestClass
Public Sub Test()
Dim chart As Excel.ChartObject
Dim workbook = chart.Parent.Parent
End Sub
End Class
Now of course, if you compile this, it will work since Option Strict is off.
But when you set it on (or port it to C#) it won’t compile, since chart.Parent returns a type of Object. And the compiler cannot find the .Parent property on that Object, so we would need to cast to ChartArea to get the .Parent property appropriately, and then cast this result to an Excel.Worksheet.
Option Strict On
Imports Microsoft.VisualBasic
Public Class TestClass
Public Sub Test()
Dim chart As Excel.ChartObject
Dim workbook As Excel.WorkSheet = CType(CType(chart.Parent, Excel.Worksheet).Parent, Excel.Workbook)
End Sub
End Class
This will work.
Unfortunately sometimes there are properties you can set, but they don’t appear in your Intellisense, so you can’t get/set that property.
If you are using VB.NET with Option Strict Off this is no problem, but again: with Option Strict On or in C# it IS a problem.
Since the late binding internally uses Reflection I thought might fetch the PropertyInfo for that particular property and set it that way:
Dim propertyInfo As PropertyInfo = GetType(Excel.Chart).GetProperty("ThePropertyYouWant")
propertyInfo.SetValue(someChart, someValue, BindingFlags.SetProperty, Nothing, Nothing, Nothing)
This won’t work either, since the compiler cannot find the PropertyInfo of that property, it just doesn’t exist. You will get a NullReferenceException. You can only set it at runtime.
The solution is:
GetType(Excel.Chart).InvokeMember("ThePropertyYouWant", BindingFlags.SetProperty, Nothing, someChart, New Object() {someValue})
This way you just say to the runtime: set that value on that property, don’t try to read the metadata first!