-4

Most questions of this type are seeking to alter the program behavior (things that could be decided at run time) or want to deal directly with debug printing. This is a bit different.

I have code that depends on a peripheral (like a card reader). Sometimes I don't use it, which means the library isn't present. (And I'm being nice, because "library" turns out to mean installing a 2GB software suite). When I remove the library, I can't open the device. If I can't open the device, I can't create the class member that uses it. With the class inoperative, I can't call its methods from within the code. Therefore, I can't just choose not to execute it; I need it to go away since it will not compile without the library.

Preprocessor directives like #if and all that are ok, maybe; but these things appear in more than one file, which means independently maintaining a #define at the top of each. I come from a simpler place (meaning, C) where one header file can be used to control this. I note that C# is rather hostile about #define (either the label exists, or not; no constants or calculations allowed), and that makes me think there's another way.

How do you handle this?

---Follow-up(s)---

I did read the "duplicate" Q/A's, and have a fairly good picture of what I'm dealing with. I didn't find those questions in my original search, but sometimes that's just how it is.

@Amy suggests that #define at the top is "not how it's done" but rather "put it on the command line". So, (if I realize we are sticking with this mechanism) the discussion might go to examining ways to have that happen . One does not simply drop to a terminal and do that. It happens as "IDE features" or "IDE hacks".

@Alexei Levenkov asks what I really want. I really want to (a) not get compile errors, and (b) do it by selectively leaving out the code. And, find the C# equivalent to the way I proposed. Some more constraints are addressed by the fact that I haven't been using VS or C# for all that long. So I know a lot less than you all do. Considering I got the code from the last person and have to deal with what I see, I don't want to set up the person after me to have to figure out what "interesting" thing I might have done to make it work. Thus, things like hand-editing a project file may work but will also cause consternation down the line.

@ Eric Lippert suggests "hostile" is really "sensible". I may have had my tongue too far into my cheek on that one. VS seems to be telling me I'm doing it wrong, so I sensed there's a "right way" I simply don't know about. As for the 2GB supporting application, I will go to various computers and pull down the repository and try out something, and so this "overhead" wants to propagate with it. It's worse if I'm linked through my phone to do the download. And if I build the application with everything included, the end user is then required to install that software suite before the program will run. In theory, they could be required to buy the software. If I sent you a tic-tac-toe game, and told you it wouldn't run until you installed Oracle, you'd probably pass on the whole thing.

I considered the "stub out the interface" idea, but there seemed to be more hooks into the class than I wanted to deal with. Plus, I don't know what these things do, so I have to know something about them in order to "fake" them.

In the end I decided that we're still largely using the #if scheme to get this done, and the replacement feature I imagined might exist, doesn't. And I'm using the provision in the project file(s) as cited by @Jim G. as it gets the job done and is only a little imperfect. It's good enough.

gbarry
  • 10,352
  • 6
  • 33
  • 43
  • 1
    Preprocessor symbols are passed in on the command line to the compiler, or part of MSBuild. Placing them at the start of each file isn't the way its done. –  Jul 09 '19 at 19:30
  • Partial classes might be a strategy to look at. I haven't given it a lot of thought, just tossing out an idea. – nicomp Jul 09 '19 at 19:33
  • Possible duplicate of [Is there anyway to #define Constant on a solution basis?](https://stackoverflow.com/questions/5268177/is-there-anyway-to-define-constant-on-a-solution-basis) – Jim G. Jul 09 '19 at 19:33
  • 1
    A C# project file can actually change which files are included in the project based on the project configuration (using the `Condition` attribute). This isn't exposed from VS, as far as I know, but it is useful for larger batches of code. Alternatively, create an API to abstract over the library that you compile different versions for, and swap out the whole assembly at runtime (or compile time, doesn't matter at that point). This assumes you have some sort of natural interface that you can easily stub out. – Jeroen Mostert Jul 09 '19 at 19:34
  • While suggested duplicate by @JimG. solves global defines the post seem to be asking for alternative to defines altogether... gbarry - could you please clarify what exactly you are trying to solve with using #if (it is unlikely size/performance as couple extra classes for solution you rejected in the beginning of the post is unlikely to matter for anything)? And what type of alternatives you are looking for? – Alexei Levenkov Jul 09 '19 at 20:35
  • 1
    2GB of storage costs four cents; why are you worrying about trivial amounts of money? Are you working in some sort of extremely resource-constrained environment? – Eric Lippert Jul 09 '19 at 20:36
  • 2
    What you consider "hostile" many people would characterize as "sensible". – Eric Lippert Jul 09 '19 at 20:36
  • One suggestion is to abstract the functions that peripheral library provides that you need to a wrapper class, then create an interface for that wrapper class. Have 3 libraries, common containing the interface declaration, a peripheral wrapper library that contains a class supporting the reader etc that implements it, and a no peripheral present library that also implements it, but throws NotSupportedException or NOOPs or whatever. Your current class then has an instance of the interface passed in to the constructor, and the assembly you load to find that can be a runtime decision. – Adam G Jul 09 '19 at 23:06

1 Answers1

1

As @BJ Safdie said here:

  • Set them in your Compilation Properties or Build options.
  • You get to the build options by right-clicking the project and selecting properties from the menu.

Project Build Options

Jim G.
  • 15,141
  • 22
  • 103
  • 166
  • 1
    This is reasonably good. Alas, the "solution" builds two projects, so one has to realize they both need to be modified. Still, it's a whole lot better than going into each source file! – gbarry Jul 11 '19 at 21:19