Garfield the Dummy Garfield the Dummy - 1 year ago 70
C# Question

Is it possible to keep precompiled symbols in C# assemblies for use in a referencing program?

I know that the C# preprocessor will generally eliminate the precompiled symbols. Can the rule be broken a bit?

For example, I have a C# dll A, which I wanna use in another C# program B. In B I have different precompiled symbols X, Y, Z. If X is defined, I need a version of A. Else if Y is defined, I need another version of A. And similar for Z. To implement this, I want to write precompiled directives in A's source code, like

public static class MyClass
public static void MyMethod()
#if X
#elif Y
#elif Z

I hope these conditions don't disappear during A's compiling and B can take use of them. Is it possible? Or what should I do to work around this?

Thanks in advance.


Some background information. B is a Unity3D Game, and A is a common library we want to use across different games. So Both A and B relies on the assembly UnityEngine.dll. Then there is various precompiled symbols defined by U3D to indicate the current build platform, the engine's version and etc, which I want to take use of in both A and B.

Answer Source

In general, you define compiler constants on a project basis. So if your shared assembly defines X and you compile it, it only contains the call to DoX(). Then you compile the actually consuming application where you define Y, but that won't affect the shared assembly.

However, compiler constants can be passed to the compiler using the command line or using XAML, and then apply to all projects that are built at the same time.

How to do so is explained in Is There anyway to #define Constant on a Solution Basis? and MSDN: How to: Declare Conditional Compilation Constants.

So that might be an option: declare them solution-wide and compile the solution as a whole. Do note that your shared assembly then only contains the call corresponding to the constant(s) defined at compile-time: you can't share that assembly with different executables compiled with different constants, because only DoX() will be called if X was declared at compile-time.

Or, rather, you dump this idea altogether and implement the proper design pattern, so the proper method will be called depending on what the caller wants, not who the caller is.

This may mean you should simply expose DoX(), DoY() and DoZ() to the caller, or let MyMethod() do something based on a passed (enum) variable, or something using a strategy pattern.

That being said, there may be reasons to do what you're trying to do, for example not leaking implementation details to competing companies who use your application.