The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

C# - enums/reflection - a design question

I have a situation:

I have an enum

enum TT {
 A,
 B,
 C
}

I have another sets of enums
enum STA {
 A1,
 A2
}

enum STB {
 B1,
 B2,
}

Conceptually,  for the enum value 'A' in TT, I would need to do something with STA and for 'B', STB and so on. Sort of a classic protocol message handling with types and subtypes.

One straightforward way to do this is to simply do a case/if

if(val == TT.A)
  //do something with val2 and STA
else if (...)

But this gets ugly if the number of TT and the sub type enums are large. So I would instead want to somehow associate the enum value with its subtype, and then work on it. I can 'feel' that reflections are a good way to do this, or I could use custom attributes - but I can't figure out how exactly to do that. Any insights/little bits of code-samples greatly appreciated.
Anil
Monday, October 24, 2005
 
 
What are you actually trying to _do_? Why can't you use classes and polymorphism?

There are static methods on Enum that you might find helpful, as I can't imagine what reflection would give you.
Thom Lawrence Send private email
Monday, October 24, 2005
 
 
Thom,

Maybe I'm not clear with my question. let's say I get 2 values
0x02, and 0x03

0x02 matches the main enum (TT) so let's say
TT.A = 0x02

now if this is TT.A, then I need to print the equivalent value of 0x03 which is defined in enum STA (look only in that enum defined which matches STA, because 0x03 could be in STA, STB, STC)

I want to do this without having to do it with if/else statements.

Even if I can use static methods in Enum, such as Enum.getValue/name etc. I need to know the type for which I need the value. I'm unable to figure out how to store that type (maybe in a hashtable) so I can then look into its defined values.
Anil
Monday, October 24, 2005
 
 
I figured it out - once I solve it in a way I hope is elegant, I'll put it for any other newbies to see, or experts to correct.
Anil
Monday, October 24, 2005
 
 
> Sort of a classic protocol message handling with types and subtypes.

I don't think that's very classic. Classic is to faithfully serialize and deserialize, not remap types on the deserialization.
That would seem the safest approach. Then you can create your objects from the deserialize object instead of skipping a step.
son of parnas
Monday, October 24, 2005
 
 
parnas,

That is possible when both sides of the system use the same objects for serialization/de-serialization. If they are disparate systems where you only receive a series of bytes that you have no route except to map pre-determined defined values, there isn't much choice. When I said classic I did not mean it in a way of designing a protocol but more in terms of 'this byte value means this' sort of thing.
Anil
Monday, October 24, 2005
 
 
> . If they are disparate systems where you only receive a series of bytes

Are you saying you can't make an object to exactly fit the bytes that stream in?
son of parnas
Monday, October 24, 2005
 
 
The best way to do it is to have a custom attribute that contains a Type object. By marking TT members with that attribute, you will know to which enum they correspond.

Like this:

enum TT
{
 [CorrespondingEnum(typeof(STA))]
 A,
 [CorrespondingEnum(typeof(STB))]
 B
}
Ioan Bizau
Tuesday, October 25, 2005
 
 
This sounds as a pretty specific task, which might call for using data structures more flexible than enums. Here is one idea or rather a code sketch, you may or may not find useful :)

enum Major
{
 A = 0x01,
 B = 0x02,
 C = 0x03,
}

enum MajorMinor
{
 A1 = 0x0101,
 A2 = 0x0102,
 B1 = 0x0201,
 B2 = 0x0202,
 B3 = 0x0203,
 C1 = 0x0301,
}
DK
Tuesday, October 25, 2005
 
 
Ioan,

That's pretty much EXACTLY what I did! I took the type as an input to my custom attribute, and then used the Enum static classe to get what I want.

Parnas,

That's the next thing I'm trying to do ;) I am new to some of this stuff in C# (am from the C world where I could often typecast an incoming stream into a struct I wanted (assuming the originator wrote it that way), but I haven't gotten there yet. If you can give me a nice link I'd be thankful too!
Anil
Tuesday, October 25, 2005
 
 
> If you can give me a nice link I'd be thankful too!

I don't think it's language specific unless you really can just type cast. I've never worked on a system that did that. Usually the data are encoded in a neutral format and must be decoded into a platform specific format. So type casting has never been an option.
son of parnas
Tuesday, October 25, 2005
 
 
Unfortunately that's the situation I'm in - the peer side simply writes a struct onto the wire. That is in C, my code is in C# - and it's not really a protocol, but just a stream coming in. I've just started reading something about structlayout and marshalling and what not, I'll get there on crutches I think!
Anil
Tuesday, October 25, 2005
 
 
>  Unfortunately that's the situation I'm in - the
> peer side simply writes a struct onto the wire.

Then create an object that represents the C data structure. Then you'll have to hard the encoding format in your code to produce the C# representation. Then your higher layer objects can construct themselves from that object. I wouldn't jump from the stream representation to the end object represnetation. It just gets to complicated and fuzzy.
son of parnas
Tuesday, October 25, 2005
 
 
Parnas,

You're completely right. That's what I'm trying to find out next - 'how do I reproduce a C struct into a C# struct, and then cast a stream of incoming bytes to this C# struct' -- Just started looking up the web to do this sort of thing.
Anil
Tuesday, October 25, 2005
 
 
>> That's what I'm trying to find out next - 'how do I reproduce a C struct into a C# struct, and then cast a stream of incoming bytes to this C# struct'

Here is a quick hack:

unsafe object GetStructFromMemoryStream(Type structType, MemoryStream stream)
{
    fixed(void* p = stream.ToArray())
    {
        return Marshal.PtrToStructure(new IntPtr(p), structType);
    }
}
Ioan Bizau
Wednesday, October 26, 2005
 
 
Remember to mark the structure with [StructLayout(LayoutKind.Sequential)]
Ioan Bizau
Wednesday, October 26, 2005
 
 
Ioan,

:) I figured that as well, implemented slightly differently - without using the marshalling.

Thanks for showing a different approach, nevertheless!
Anil
Wednesday, October 26, 2005
 
 
How did you do it?
Ioan Bizau
Wednesday, October 26, 2005
 
 
myStruct ms;       

      unsafe{
            fixed(byte *bufHdr = buf) {
            ms = *(myStruct*)bufHdr;
            } 
    }               

where myStruct is the struct I've defined within my C# code. Works like a charm.
Anil
Wednesday, October 26, 2005
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz