Click here to Skip to main content
15,884,836 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am writing a generic class in VB.Net 2010 to use in multiple programs and would like the class to utilize generic property names so that I can simply copy the class between files and keep it the same. The problem I have is that it would be much more useful if each different instantiating program were able to 'alias' the property names such that intellisense would use the alias but I wouldn't have to rewrite all the properties names in the class. Something such as

VB
Class BitFlags

    Public Property flag0 As Boolean
        Get
            Return GetBit(0)
        End Get
        Set(ByVal Value As Boolean)
            If Value = True Then SetBit(0)
            If Value = False Then ResetBit(0)
        End Set
    End Property


End Class


and where the instantiating program could do something like this

VB
dim myflags = new BitFlags
'some alias function
Alias myAlias = myflags.flag0

myAlias = True
myAlias = False


Thank you!
Posted

First of all, the answer: no there is no such thing.

You can get some similar effect, but it cannot be the alias or behave exactly like the alias.

I don't want to discuss the rationale behind what you want by a very simple reason. I can see this: "I can simply copy the class between files and keep it the same". Since that moment, you are not going to do any programming, you are going into such a huge abuse that any programming activity would not make any sense at all; this would be a totally wrong way.

I would be happy to help you here, but I don't know how at this moment, as I cannot see where is your confusion. Anyway, I don't see how the alias of the property could be useful, what kind of abstraction could it provide. I don't think it could.

In the example you show, I don't even see a need in generic. A bit is a bit. You set it or clear (clear, not "reset"), by some index (bit shift). If you want to know how to do it, I can show you. Perhaps you need to explain your ultimate purpose, to get further help.

[EDIT #1]

Two more notes:

Your code looks like the class System.Collections.BitArray: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx[^].

You may need to look at this class to get some basic ideas. If you want to know how it works, I can explain you. This is a pretty simple thing.

Also, there is no such thing as "class property". A property can only be a member of a class or a struct. In some languages, "class property" is a more precise term for what is usually called "static property" in .NET, so this term is at least confusing.

[EDIT #2]

After the clarification in OP's comment below:

Please see my comment in reply, about the use of enumeration types. I have a detailed article on related topic which should help you: Enumeration Types do not Enumerate! Working around .NET and Language Limitations[^].

—SA
 
Share this answer
 
v3
Comments
Makulais 15-Jan-13 8:01am    
Sergey,

Thank you for your time and answer. I did use the wrong term, I was wanting to be able to alias the name of a property member of a class. I am writing code for a UI interface to machines, typically the controllers on them utilize integer words which allow access to individual bits. So I would have a 32bit word that represents all the different states of a single axis, and say 4 axes, another 32bit word that represents all the inputs on an IO card, another 32bit word that represents the different states of the controller itself, ... Each bit would act as a flag, the axis/controller/IO card or user will set or clear (reset is the terminology used there) individually, yet the word itself represents the status. If there is no status available, you aren't configure, or homed, or ..., you simply compare to zero. If the word value is less than say 2^7, then there is no error, only status to read, such as idle, moving, accelerating, decelerating, ...

I wanted to create a representation of this in my code, a class is typically used to represent a physical object. Please understand I have had no formal training in OOP, and work by myself so am limited in my resources and background.

So the rationale was to develop a class to represent these words, then in a single program I could have multiple instances to represent the different words with non-confusing terms for each individual property or bit of each different words. By aliasing the property members of the class I would be able to do this.

So I am definitely not sure if I am approaching this correctly, but I can't seem to figure a way to do it. The System.Collections.BitArray is similar, but it won't let me name each individual bit will it? I would be required to use the ClassName.BitArray(n) value to represent a bit, not very descriptive.

Thanks again for any and all help.
Sergey Alexandrovich Kryukov 15-Jan-13 10:49am    
Thank you for these clarifications.

Here is what you can do: instead of integers, use enumeration types, and give every member its semantic name.
Use bitwise arithmetic to combine, set, and clear of separate bits (corresponding to separate members of enumeration types).
—SA
Makulais 15-Jan-13 8:18am    
Sergey,

One other thought, I am currently attempting to use the <flagsattribute()> for individual enumerations representing each word, it looked like it would work but I can't figure out a single function to create the word from the different enumerations? From my testing and reading, I have to create a new function for each different enumeration.
Sergey Alexandrovich Kryukov 15-Jan-13 10:47am    
This attribute does not effect anything at all except the output of ToString.
What is "the word from the different enumeration".
—SA
Makulais 15-Jan-13 11:20am    
As you surmised, I couldn't get that to work either as it made no affect. The word would be the integer representation of the bits. if bit 0 and bit 3 were set, the integer value would be 9. Keys to my need/wish are the ability to set/clear each bit individually by calling each a unique name, to be able to read the entire bit array as an integer, and to be able to easily and with a minimum of programming create new bit and word/integer variables. I just thought if I could implement a class and alias the property members in the instantiating program it would be great. I'm trying structures, enumerations, ... but can't get any of it all to work the way I want without using reflection which i'm told is bad? I'm about to give up and either type up an enumeration and a function to create the integer value for each word or use the reflection. :(
I have a background in Industrial Automation and I understand what you are trying to do. I suggest you write a base class that implements the word-length in the controller. I would suggest something that would support both 16 and 32 bit word lengths (unless you know you will always be working against a 32-bit system). You could take the desired length in the class constructor specifying a default value.

Internally, I would keep the bits in an array. It will make accessing them easy. You can then write class properties that access individual bits (bit0, bit1, etc) another that accesses the whole array (bits), and other ones that provide the bits in convenient chunks... like LWORD or HWORD for the low and high halves. You could probably also provide a MSB (most significant bit) and LSB (least significant bit) properties that would return int values equal to the MSB or LSB. This is often handy for error or status displays on HMI's where you need the concept of a "priority" level.

Once you have created the class that implements one word or double-word in the PLC, you can simply create classes which derive from the first class and add specifics... And with virtual methods, you can specify a method that knows how to 'peek' or 'poke' the memory location in the PLC. In reality, the base class knows nothing of how you would do that but the derived classes would have concrete instances of those functions that know how to talk to the PLC or to field I/O over whatever method you are using (EthernetIP, DeviceNet, etc).

Message me directly if you need some additional direction on this. I'd like to hear about your project. OOP principles can be very powerful when applied to automation projects because of the inherit redundancy in the way the systems are built and the manner in which OOP can address that redundency. If you architect these base objects correctly, your system should be very flexible.
 
Share this answer
 
Comments
Makulais 15-Jan-13 18:50pm    
Jason, I have considered that solution, but it's rather cumbersome in that inside of VB the references are to, as you said, bit0, bit1, ... I was hoping to write a base class to implement the functionality, but to have bits named the same as they are in the PLC's description. The base class would have generic terms, bit0, bit1, bit2, ... but then I would simply redefine the bits in the instantiating program and leave the class alone. That way if I have, for example, 10 different words(in the PLC) to work with, I would only have one class with 10 instances, but the bits of each word would be unique to that word. I have attempted it with property members of a class, structures, and enumerations, but can't find a solution without resorting to either writing an individual class for each word, or an individual structure for each word with it's own function to return the integer value of the word.

I have found this, http://www.codeproject.com/Articles/6792/Masks-and-flags-using-bit-fields-in-NET
but haven't had a a chance to implement it. I have converted it to VB and will be trying to work with it the next few days. The author states that you can name the flags whatever you want, but I'm afraid he's talking about from inside the class.

In this specific case, I'm not actually using a PLC, otherwise I would use the PLC's address and just call or set the different values from it, no problems. The PLC would be left to handle the math and everything else automatically. I would have my word and bits exactly defined as I want. But in this case I am using a Kollmorgen Synqnet controller, no PLC, and would just like to emulate some of the functionality for ease of use and consistency with coding methods used on the PLCs.

Thanks for you input and any other ideas you may have.
Jason Gleim 16-Jan-13 10:12am    
OK... I think I understand what you are going for. I'm not aware of a means to do exactly what you are looking to do but I think there is a workaround that would reduce the amount of work you would have to do but still allow you to work with friendly names in derived classes.

So if I understand you correctly, you want a base class (something like "BitBaseClass") with properties bit0 thru bit 31. You would like to inherit that class creating an instance for each block of memory, for example "Station1", "Station2", "Station3", so that you get all of that storage and bit mechanisms in those derived classes for free. But rather than address bits as Station1.bitX, you would rather address it as Station1.EndOfTravelPositive but use bitX in the base class as the storage bit. The problem here, of course, is that to expose "EndOfTravelPositive" on the derived class means manually creating that property and getting/setting bitX as the backing store for that property. If each "friendly" bit in the project has to be done this way then what is the point of the base class?

The bad news is that there is no way to alias a property in the way I think you want to do it. If would be nice if you could markup a property with something like:

[PropertyAlias="EndOfTravelPositive]
Public Property Boolean Bit0

... but alas, there is no such thing.

That being said... there may be a method that would get you close to what you want. It is possible (and not that hard really) to use reflection to get and set property values at runtime BY NAME. Therefore, in a derived class such as "Station1" it would be possible to get and set the underlying "bitX" properties in the base class simply by name. Your derived classes would then have a method, such as "SetBit(bitName as string)" and GetBit(bitName as string) where you would match up a friendly name like "EOTPositive" to a backing bit property (say bit7) and then use reflection to get/set the bit7 backing value. You would maintain these mappings (between friendly name and bit location) in a dictionary (which is a key/value pair collection) allowing you flexibility in naming the bits. The only drawback is you would NOT get Intellisense for friendly names in this case. The Station1 class, for example, would show bit0 to bit31 properties and the GetBit/SetBit methods, but since the friendly names exist internally in the dictionary, they would not pop-up... you would have to know the names when working with them in the class. (Although if you wanted to hard-code them into an enum, you could work with that and it would give you Intellisense)

Since the mapping dictionary gives you the ability to easily change the friendly names/bit mappings, you can persist that information in a data table or an XML file. You could even go a step further if you had multiple 'station' classes by creating a dictionary of stations driven from a similar config. Then your machine configuration is completely dynamic and could be changed with a simple configuration file. Of course, the logic for each station would likely be different but there are some schemes which could address that as well.

While this wouldn't fit exactly what you want, I think it would give you the flexibility you would want without too much hard-coding or a lot of extra copy/paste/change work.
Makulais 16-Jan-13 14:42pm    
Jason, you understood my problem exactly. And you understood that 'alas, there is no such thing!' :(

I did consider doing it with reflection, see my notes above, but was told it was wrong, rude, inconsiderate, slow, performance degrading, ... by the code police. I also typically get that I'm just lazy and shouldn't mind typing but that one went by this time without being stated. I guess one of my issues in programming with OOP is that I thought one of the basic tenants of the concept of OOP was re-usability of code. The ability to create a class, or assembly and re-use it in multiple instances or projects without having to redo it.

The intellisense was the big reason i wanted to alias it, it makes reading and understanding the code now, and 10 years from now, so much easier. I have machines that i built that are still running under DOS from 20 years ago that I still have to support! Anyway, i appreciate your help, you can find me at www.machaet.com, we might be able to hook up for a beer sometime and discuss projects. It would be nice to have a good reference for questions and methods sometime also. Thanks again.
Jason Gleim 16-Jan-13 14:59pm    
Yea... eff the code police... too many people willing to tell you that you shouldn't be doing this or that when it does nothing to address the problem you really have. When it comes down to it, you need to do something that makes the most sense for the project even if it doesn't "follow the rules".

You are right, OOP is designed for reuse but there are no hard and fast rules there. You have some natural encapsulation around a 32-bit dword because you can easily represent a node of system memory. Ideally, that is your atomic unit which has properties and methods on it and can be re-used by extension throughout your application. Sometimes that just doesn't work out. I looked at your solution you posted and it will certainly work. It is straight forward and self describing. If I were you I'd walk away knowing what you have done will work.

If I'm ever in KC I'll have to look you guys up. In in Columbus, OH and don't get that far west too often. Best of luck!
Gave up and will be utilizing an enumerated list initialized with 2^n powers and performing bitwise operations and setting my word/integer value to the enumerated values for each word/integer that I will be working with. Its not as nice as working with the bits individually but it will work. Thanks everyone for suggestions and pointers, I appreciate them all.

VB
<flagsattribute()> _
    Public Enum Machine_State_Enum_Flags As ULong
        InitializationNotComplete = 0
        ControllerInitializing = 1
        MachineError = 2
        ControllerError = 4
        DriveError = 8
        MotionError = 16
        ExternalError = 32
        EStop = 64
        Idle = 128
        Pause = 256
        InCycle = 512
        Homing = 1024
        Moving = 2048
    End Enum
#End Region

       Private Sub machine_state_test()

        Dim machine_state As Machine_State_Enum_Flags = 0
        'using bitwise operations, this statement adds the value of Machine_State_Enum_Flags.InitializationNotComplete
        ' to the machine state by setting the desired bit
        machine_state = machine_state Or Machine_State_Enum_Flags.Moving
        Debug.Print("machine state is: " & machine_state & ", " & machine_state.ToString)
        machine_state = machine_state Or Machine_State_Enum_Flags.InCycle
        Debug.Print("machine state is: " & machine_state.ToString)

        'to check and see if a specific flag is set on machine state,
        If (machine_state And Machine_State_Enum_Flags.Moving) > 0 Then
            Debug.Print("moving flag is set")
            Debug.Print("machine state is: " & machine_state.ToString)
        End If

        'to clear a bit on the machine state
        machine_state = machine_state Xor Machine_State_Enum_Flags.Moving
        Debug.Print("machine state is: " & machine_state.ToString)

    End Sub
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900