I am working with a COM library in Visual Basic (VB.NET). I am trying to get a list of properties associated with an Interface; however, I am not able to get a list of interface properties. Can someone direct me on the best way to list properties on an Interface?
Below is some sample code that loops over all the properties of a class called "TextBox". The output from this code is a list all the class properties.
This particular code doesn't seem to work for interfaces. By this I mean that this code doesn't return the properties of an interface.
Dim txt As New TextBox
Dim type As Type = txt.GetType()
Dim properties() As PropertyInfo = type.GetProperties()
For Each p As PropertyInfo In properties
OutputWindow(p.Name)
Next
Image of COM Library with Interface HYSYS.Valve
Just replace txt.GetType() with the GetType() operator to specify type names instead:
Dim type As Type = GetType(HYSYS.Valve)
You would only use <object>.GetType() when you already have an existing instance of an object. To get the properties of a type in general, for instance a TextBox, it is better to do GetType(TextBox).
Related
I am trying to loop through all of the controls in a panel. Some of the controls as classes that I created. In those classes, I want a subroutine run when the object is removed. So I am trying to create a temporary object that I can use to run that routine.
For Each window As Control In main_window.Controls
If window.Handle = hdl Then
Dim temp_window as window.getType()
temp_window.close_me()
main_window.Controls.Remove(window)
End If
Next
However, the getType assignment is not allowed.
How can I accomplish this?
Object.GetType is not what you want, it returns the Type instance of the object which contains meta data of that type, normally used for reflection.
What is the actual type that you want? It has to have a close_me method. You could use OfType:
Dim windowsToClose = main_window.Controls.OfType(Of YourWindowType)().
Where(Function(w) w.Handle = hdl).
ToArray()
For Each window In windowsToClose
window.close_me()
main_window.Controls.Remove(window)
Next
Your For Each doesn't work for another reason: you can't remove items from the collection while you are enumerating it. Above approach stores the windows you want to remove in an array.
The right way to do this is to use a base class that your controls Inherit or an interface that your controls Implement with close_me on the base or interface. Then, you can TryCast each member of Controls to the base or interface and, if it succeeds, call close_me on it. If you use the base class approach, you may wish to make it abstract (MustInherit) and then close_me would be MustOverride, depending on if the behavior should be different in each derived type.
e.g. assuming you use ICloseable,
Interface ICloseable
Sub close_me()
End Interface
'...
For Each window As Control In main_window.Controls
If window.Handle = hdl Then
Dim asCloseable = TryCast(window, ICloseable)
If asCloseable IsNot Nothing Then
asCloseable.close_me()
EndIf
EndIf
Next
As I am trying to figure out how to work with the Siemens Tia Portal Openness framework, I try to find an item in my Tia Portal project with the ControllerTarget type.
I try to find the items like this:
Imports Siemens.Engineering
Imports Siemens.Engineering.HW
Module Module1
Sub Main()
Dim myTiaPortal
myTiaPortal = New TiaPortal(TiaPortalMode.WithoutUserInterface)
'The portal is open, now create a project.
Dim tiaProject As Project
'Open the sample project:
Dim fileName As String
fileName = "C:\Path\To\Project\Sample_Project.ap13"
tiaProject = myTiaPortal.Projects.Open(fileName)
'Get the frist device from the project:
Dim tiaDevice As Device
tiaDevice = tiaProject.Devices.First
For Each item As IDeviceItem In tiaDevice.DeviceItems
Console.WriteLine(item.GetType())
Next
Console.ReadKey()
End Sub
End Module
This shows two items in the project:
Siemens.Engineering.HW.DeviceItemImplementation
Siemens.Engineering.HW.ControllerTargetImplementation
When I try to define an object of the type ControllerTargetImplementation I get the message that this datatype does not exist.
When I try to convert the item of type ControllerTargetImplementation to an object of type ControllerTarget, this seems to work perfectly.
Does this mean that the type returned by GetType() does not have to be the same as the actual type of the object? Is this normal? Or is this a strange thing in the openness platform?
When I try to define an object of the type ControllerTargetImplementation I get the message that this datatype does not exist.
Types can be internal to an assembly, which means that while they exist and things like GetType will show them to be there, you can't use them directly.
When I try to convert the item of type ControllerTargetImplementation to an object of type ControllerTarget, this seems to work perfectly.
Given the names involved here, it certainly sounds like ControllerTarget is the type being exposed to you, the consumer of the library, while the implementation of that type, perhaps a subclass or an implementation of an interface (ie is ControllerTarget a class or interface?) is hidden from you as you don't need to know about how it does it's job, nor interfere with it.
Does this mean that the type returned by GetType() does not have to be the same as the actual type of the object?
The actual type of the object is what is reported by GetType, but that doesn't mean that it's necessarily what you refer to it as. For instance, consider the following:
Class A
End Class
Class B
Inherits A
End Class
Sub Main
Dim obj as A = new B()
Console.WriteLine(obj.GetType())
End Sub
This will report obj as having a type of B (because that's the actual type we instantiated with new B()), even though it's stored against a variable of type A.
I apologize for the vague question, but I'm unsure how to proceed.
What I need is something that works like a class object with various fields and properties for storing data. But, since not all the fields/properties are known at the compile time, I also need to be able to add and use new fields/properties in runtime.
These objects would later be arranged in lists, sorted by the values in those fields/properties and bound to WPF controls.
For now I'm using just that: class objects with various properties, but I'm starting to run into problems, where I need to add more fields/properties.
Is there something I could use to achieve this in vb.net?
Edit:
Ok, I'll try to illustrate.
Currently I have something like this.
Let's say I have defined an object like this
Public Class DataEntry
Public Property Name As String
Public Property Type As String
Public Property Msc As Integer
End Class
That works fine if I know all the properties I will have at the start. I run into problems if I suddenly need to add another property:
Public Class DataEntry
Public Property Name As String
Public Property Type As String
Public Property Msc As Integer
Public Property AdditionalDescription As String
End Class
Of course, I could recompile the whole thing, but since I don't know all the possible properties I will be needing in the end, I was wondering, maybe there is a way to achieve this from runtime?
Or should I just use complicated heap of arrays instead of custom objects?
It's not possible to add new properties to a class during run time.
If you don't want to add properties to the class ahead of time which you might not use, then you could instead use a dictionary to store 'properties' which you're not aware of until run time.
Public Property RunTimeProperties As New Dictionary(Of String, Object)
A dictionary which holds values of type 'Object' can store just about anything. Strings, Arrays, Lists etc.
RunTimeProperties.Add("Length", 100)
RunTimeProperties.Add("Height", 200)
RunTimeProperties.Add("MiddleName", "Rupert")
RunTimeProperties.Add("SiblingsNames", New String() {"John", "Sarah", "Michael"})
You can use the TryGetValue method to get the values out of the dictionary.
Dim value As Object
If RunTimeProperties.TryGetValue("Length", value) Then
' Length was found in the dictionary
Else
' Length was not found in the dictionary
End If
Hi all
I have handle of a usercontrol on external application in vb.net.
I know class type of that user control.
I want to get refrence to that object to check some properties of that object.
Is it possible and how?
thanks
I hope I do understand your question right...
You may try to insert a reference to your library (I assume your userControl is in this library). As a prerequisite this external application must be written in .Net or have some kind auf COM interface!
Then you may try to access the userControl class by
NAMESPACE.CLASS myReference = new NAMESPACE.CLASS();
hth
You can get some info by using interop, with some functions like GetWindowText and SendMessage, however this won't allow you to get all properties, and won't work on every type of application (WPF or Java come to mind).
The Control Class has a method FromHandle:
Dim myCtrl As knownType = Control.FromHandle(knownHandle)
'then get the known property using Reflection
Dim oProp As System.Reflection.PropertyInfo = myCtrl.GetType.GetProperty("KnownProperty")
Dim oValue As Object = oProp.GetValue(myCtrl, Nothing)
'or directly:
Dim oValueD as Object = myCtrl.knownProperty
I don't know if it works between processes.
Does anyone know how to iterate over a generic list if the type of that list isn't known until runtime?
For example, assume obj1 is passed into a function as an Object:
Dim t As Type = obj1.GetType
If t.IsGenericType Then
Dim typeParameters() As Type = t.GetGenericArguments()
Dim typeParam As Type = typeParameters(0)
End If
If obj is passed as a List(Of String) then using the above I can determine that a generic list (t) was passed and that it's of type String (typeParam). I know I am making a big assumption that there is only one generic parameter, but that's fine for this simple example.
What I'd like to know is, based on the above, how do I do something like this:
For Each item As typeParam In obj1
'do something with it here
Next
Or even something as simple as getting obj1.Count().
The method that iterates over your list can specify a generic type:
Public Sub Foo(Of T)(list As List(Of T))
For Each obj As T In list
..do something with obj..
Next
End Sub
So then you can call:
Dim list As New List(Of String)
Foo(Of String)(list)
This method makes the code look a little hairy, at least in VB.NET.
The same thing can be accomplished if you have the objects that are in the list implement a specific interface. That way you can populate the list with any object type as long as they implement the interface, the iteration method would only work on the common values between the object types.
If you know that obj is a Generic List. Then you're in luck.
Generic List implements IList and IEnumerable (both are non-generic). So you could cast to either of those interfaces and then For Each over them.
IList has a count property.
IList also has a Cast method. If you don't know the type to cast to, use object. This will give you an IEnumerable(Of object) that you can then start using Linq against.