Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C/++/# Alternative to #include files when using C#

  1. May 22, 2017 #1

    berkeman

    User Avatar

    Staff: Mentor

    I'm using C# to write some code for a manufacturing test of an embedded system device. It will access several instruments that are making measurements on the device, including some National Instruments MIO channels and a Tektronix power analyzer.

    I'm most familiar with C and Tck/Tk, and am learning C# as I go. I see that there is no mechanism for #include files in C#, and have been reading about the alternatives like here:

    https://forum.unity3d.com/threads/c-and-the-best-equivalent-of-include-from-c-c.258241/

    I definitely need to be able to pull my configuration information out into separate files, preferably with separate files for each instrument that I'll be controlling. What would you recommend as the best/easiest way to do this in C#?

    Here is an example of a single C# console app file that controls some power relays that are part of the test setup. I put the configuration information into the main file for now, until I learn how to break that info out into a separate file. Thanks for your help.

    Code (C):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO.Ports;
    using System.Threading;

    namespace SimpleRelayControl1
    {
        class Program
        {
            static SerialPort serialPort2;
            static Byte[] r1on  = new Byte[6] { 0xAA, 0x03, 0xFE, 0x6C, 0x01, 0x18 };
            static Byte[] r1off = new Byte[6] { 0xAA, 0x03, 0xFE, 0x64, 0x01, 0x10 };
            static Byte[] r2on  = new Byte[6] { 0xAA, 0x03, 0xFE, 0x6D, 0x01, 0x19 };
            static Byte[] r2off = new Byte[6] { 0xAA, 0x03, 0xFE, 0x65, 0x01, 0x11 };
            static Byte[] r3on  = new Byte[6] { 0xAA, 0x03, 0xFE, 0x6E, 0x01, 0x1A };
            static Byte[] r3off = new Byte[6] { 0xAA, 0x03, 0xFE, 0x66, 0x01, 0x12 };
            static Byte[] r4on  = new Byte[6] { 0xAA, 0x03, 0xFE, 0x6F, 0x01, 0x1B };
            static Byte[] r4off = new Byte[6] { 0xAA, 0x03, 0xFE, 0x67, 0x01, 0x13 };
            static Byte[] allon = new Byte[6] { 0xAA, 0x03, 0xFE, 0x82, 0x01, 0x2E };
            static Byte[] alloff = new Byte[6] { 0xAA, 0x03, 0xFE, 0x81, 0x01, 0x2D };

            static string inputString = "";

            static void Main(string[] args)
            {
                // Define COM port for Relay control
                serialPort2 = new SerialPort();
                serialPort2.Close();
                serialPort2.PortName="COM4";
                serialPort2.Encoding = System.Text.Encoding.GetEncoding("Windows-1252");
                serialPort2.BaudRate=115200;
                serialPort2.DataBits = 8;
                serialPort2.Parity = Parity.None;
                serialPort2.StopBits= StopBits.One;
                serialPort2.Handshake= Handshake.None;
                serialPort2.Open();

                while(inputString != "exit")
                {
                    Console.Write("Relay> ");
                    inputString = Console.ReadLine();
                    switch(inputString)
                    {
                        case "r1on" :
                            serialPort2.Write(r1on, 0, 6);
                            break;
                        case "r1off" :
                            serialPort2.Write(r1off, 0, 6);
                            break;
                        case "r2on":
                            serialPort2.Write(r2on, 0, 6);
                            break;
                        case "r2off":
                            serialPort2.Write(r2off, 0, 6);
                            break;
                        case "r3on":
                            serialPort2.Write(r3on, 0, 6);
                            break;
                        case "r3off":
                            serialPort2.Write(r3off, 0, 6);
                            break;
                        case "r4on":
                            serialPort2.Write(r4on, 0, 6);
                            break;
                        case "r4off":
                            serialPort2.Write(r4off, 0, 6);
                            break;
                        case "allon":
                            serialPort2.Write(allon, 0, 6);
                            break;
                        case "alloff":
                            serialPort2.Write(alloff, 0, 6);
                            break;
                    }
                }
                serialPort2.Close();
            }
        }
    }

     
     
  2. jcsd
  3. May 22, 2017 #2

    Filip Larsen

    User Avatar
    Gold Member

  4. May 23, 2017 #3

    berkeman

    User Avatar

    Staff: Mentor

    Thanks @Filip Larsen I'll give that a try. Can I still name my supporting files *.h, or do they need to be *.cs files as well?
     
  5. May 24, 2017 #4

    Filip Larsen

    User Avatar
    Gold Member

    Since you are going to reformat your file content anyway if you are going to use partial classes for this (since you need your "configuration" inside at least a namespace and a partial class definition in each file) I would recommend going with using cs-files. Even if it is possible using *.h file for C# it is most likely going to confuse the poor humans involved. :wink:

    If you have a lot of such configuration files in a simple format and are reluctant to reformat it to C# format, then perhaps instead you can parse them and generate the C# files at compile time (e.g. transpilation), or parse them at runtime during start-up as regular data. Once you start to treat the configuration as data there is no end to how fancy you can make it or how many libraries and tools you can get to help you.
     
  6. May 26, 2017 #5

    berkeman

    User Avatar

    Staff: Mentor

    Thanks @Filip Larsen that worked. I used the *.CS extension, and for now have the extra file(s) in the same directory as the Main program. I used the same Namespace in each file, and the same Partial Public class name.

    The only trick that it took me a few minutes to figure out is that it works best to add a new blank C# Class file to the Project first, and then copy the code into it. I first tried creating the file with the code and then trying to associate it as a Class file with the Project, but wasn't able to figure that out in Visual Studio. There probably are ways to do it, but I'll stick with adding the new blank Class files to the Project first, and then putting code into them.

    Thanks for the tips! :smile:
     
  7. May 29, 2017 #6
    Often one uses serialization to accomplish these kind of things (configurations and settings). In fact I'm planning to do a similar thing to load messages, states etc; used in a protocol I'm meant to implement.
    Often one uses xml serialization but in this case binary might be equally if not better suited.
    Since the advantage of easily editable xml is moot with most byte-values (imho) although this link seems to suggest they can be stored in a hexadecimal representation.

    It seems like byte arrays are stored as base64 strings which could be generated by you.

    I however would likely build a simple tool to generate the xml files, that way you get the best of both worlds and an easily extendable solution (e.g. use a list of byte arrays and create a generic class to run the tests taking an xml file in it's constructor)

    You then make a class e.g.

    Code (Text):

    public class InstrumentName {
        public byte[6] rOn {get; set;}
        public byte[6] rOff {get; set;}
    }
     
    By decorating this with suitable attributes you'd be able to store the classes as xml and read them when needed.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted