The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
I have written a couple of classes of which are helper classes which can help with multiple other classes. Complex story, but here's the thing.
I want some of the code only available if another class is also added to the solution. I was looking into C# Preprocessor Directives and tried to do the following:
Class1.cs:
#define Class1
Class2.cs:
#if Class1
// Some code
#endif
That didn't work. The conditional statement should be in the same file appairently.
How can I dis/enable code by checking if a specific class exists? Or is what I want kinda impossible?
Hi Stefan.
From my viewpoint Visual Studio is somewhat leaky about this kind of stuffs.
Preprocessing is available only in two flavors: scoped within a module in which is declared and project-wide, by declaring in the project-property wizard.
I am not sure to understand what you want to do, but the "partial" keyword does fit your need?
Cheers
Biggest fault of Netduino? It runs by electricity.
Class OutputPortShift
{
// A bunch of code
public OutputPortShift(Ic74HC595 IcOut, Ic74HC595.Pins Pin, bool InitialState)
{
// Constructor when creating an outputport behind the Ic74HC595 IC
}
public OutputPortShift(IcTLC5940 IcOut, IcTLC5940.Pins Pin, bool InitialState)
{
// Constructor when creating an outputport behind the IcTLC5940 IC
}
// A bunch of code
}
Both IC's can be driven with the same outputport-class, but for example the enumeration of pins is different (the 595 is an 8 pins bitshifter, the 5940 is a 16 pins led driver), and a few other calls, so it has more constructors and a few switch statements later on.
But when only one of those IC's is required, it's a waste of memory if also the other IC's should be loaded because of dependency issues.
So if I could place a #define statement in Ic74HC595.cs and IcTLC5940.cs and a #if statement in OutputPortShift.cs the code would be compiled as clean as possible.
IMHO better would be to define an abstract interface that describes the common functionality (of a shift register) and use it in the OutputPortShifter class, and then derive specific classes for each shift register, something like:
public interface IShiftRegister
{
// Just example
void Reset();
void Write(byte[] data);
void Latch();
int NumberOfOutputs { get; }
}
public class OutputPortShift
{
public OutputPortShift(IShiftRegister shiftRegister, bool initialState)
{ ... }
}
public class Ic74HC595 : IShiftRegister
{
public void Reset()
{
// Actual implementation here
}
public int NumberOfOutputs
{
get { return 8; }
}
// The rest of IShiftRegister methods
}
public class IcTLC5940 : IShiftRegister
{
public void Reset() { ... }
public int NumberOfOutputs
{
get { return 16; }
}
// The rest of IShiftRegister methods
}
You could also implement the common functionality in a base class, say ShiftRegister : IShiftRegister, and derive IcXXX from it, overriding just what is different. Regarding the pin enumeration, I would need to see the intended usage scenarios, but in all likelihood it would be better to use (e.g.) a collection (IEnumerable) or a hardware provider class/interface. I am afraid though, such redesign would mean to completely change the existing code (?).
Completely change the existing code wouldn't be my biggest issue
The point is, the pins aren't hardware pins, they form a 8 or 16-bit byte together. When having more IC's in a chain (is also possible), they will even form bigger byte sequences.
I already thought of a few alternatives, going to work on it tonight. I got two evenings 100% free for this project
I was just hoping there would be a nice and easy solution to implement.
My current best solution is to add at the top of my OutputPortShift-class:
// Please define the used IC's here
#define Ic74HC595
#undef IcTLC5940
I already considered interfacing but that gives a problem with the enumeration of the pins, and one thing I really really like of Visual Studio is how it handles these things and automaticly does suggestions based on the constructor and Documentation Comments.
When I type, for example:
Ic74HC595 IcOut = new Ic74HC595(SPI_Devices.SPI1, Pins.GPIO_PIN_D10);
OutputPortShift pin1 = new OutputPortShift(IcOut,
it will automaticly suggest all available pins based on the correct constructor. I love it Makes things very easy to code and prevents typos.
Hmmm...
As far I know there's no way to solve with preprocessing directives.
Also, the closest solution I may suggest you is the following:
class OutputPortShift
{
public OutputPortShift(IcShifterBase IcOut, int Pin, bool InitialState)
{
// Constructor when creating an outputport behind the Ic74HC595 IC
}
}
interface class IcShifterBase
{
//common members
}
class Ic74HC595 : IcShifterBase
{
public const int GPO_PIN_D0 = 0,
public const int GPO_PIN_D1 = 1,
public const int GPO_PIN_D2 = 2,
public const int GPO_PIN_D3 = 3,
public const int GPO_PIN_D4 = 4,
public const int GPO_PIN_D5 = 5,
public const int GPO_PIN_D6 = 6,
public const int GPO_PIN_D7 = 7
// A bunch of code
}
// ...rest is the same...
I do not like your method to manage the compilation based on the presence of a certain class.
I would prefer having some costless abstraction that won't collide, even with both the classes included in the project.
Using this way there's no collision at all and the cost of implementation is even lesser than using enums. As far I know the "const" is translated compile-time (so that will fall in the flash), the enum is a kind of array stored in ram.
The only difference I see is about the intellisense: using enums is automatic, while using const pushes you typing at least the type name.
Cheers
Biggest fault of Netduino? It runs by electricity.
The only difference I see is about the intellisense: using enums is automatic, while using const pushes you typing at least the type name.
Cheers
It also is a form of typehinting, if you fill in 8 for example, the parser won't give an error, but there is no pin 8 (0 to 7). With an enumeration this is forced to only the real possibilities.
Hmm I have some thinking to do and some choices to make...
With an enumeration this is forced to only the real possibilities.
False: the constraint is apparent.
You may OR any combination of enums' items and you may cast to any int also. If you want a strict checking on what the user may insert, you must parse every single possibility.
Biggest fault of Netduino? It runs by electricity.
I think the "partial class" approach would work well here. Mario briefly mentioned "partial" but perhaps it helps to provide an example. I will modify the example you posted:
Ic74HC595.cs:
class Ic74HC595
{
public enum Pins
{
GPO_PIN_D0 = 0,
GPO_PIN_D1 = 1,
GPO_PIN_D2 = 2,
GPO_PIN_D3 = 3,
GPO_PIN_D4 = 4,
GPO_PIN_D5 = 5,
GPO_PIN_D6 = 6,
GPO_PIN_D7 = 7
}
// A bunch of code
}
partial class OutputPortShift
{
// A bunch of code
public OutputPortShift(Ic74HC595 IcOut, Ic74HC595.Pins Pin, bool InitialState)
{
// Constructor when creating an outputport behind the Ic74HC595 IC
}
}
IcTLC5940.cs:
class IcTLC5940
{
public enum Pins
{
LED_0 = 0,
LED_1 = 1,
LED_2 = 2,
LED_3 = 3,
LED_4 = 4,
LED_5 = 5,
LED_6 = 6,
LED_7 = 7,
LED_8 = 8,
LED_9 = 9,
LED_10 = 10,
LED_11 = 11,
LED_12 = 12,
LED_13 = 13,
LED_14 = 14,
LED_15 = 15
}
// A bunch of code
}
partial class OutputPortShift
{
public OutputPortShift(IcTLC5940 IcOut, IcTLC5940.Pins Pin, bool InitialState)
{
// Constructor when creating an outputport behind the IcTLC5940 IC
}
}
OutputPortShift.cs:
partial class OutputPortShift
{
//the remainder of the code for OutputPortShift
}
Do you see what's happening here? The existence of the file Ic74HC595.cs adds a new class called Ic74HC595 and also enhances the class OutputPortShift. A similar thing happens for IcTLC5940.cs.
@Corey
I was on the clouds!
I didn't realize that placing constructors into guess classes is an overload and *NOT* a collision!
My age rises and neurons falls...
Cheers
Biggest fault of Netduino? It runs by electricity.