Reputation: 20658
I am making a class library Foo
(Xamarin Android Library if relevant but I prefer a general .NET solution if possible), and I need something like this:
if (builtInDebugConfig)
{
this.DoSomething();
}
Now Foo.dll
will certainly be compiled in Release mode when the above code is called. Therefore #if
is not possible for sure, (the answer of the question and my test confirms Conditional
should not work also (correct me if I am wrong, I've read it's a compiler attribute too)Conditional
works). The closest I could think of is Debugger.IsAttached
, however most of the time we test apps without a debugger attached.
Is there a way to detect if the calling assembly is compiled with DEBUG
symbol/config? If possible I don't want the calling (app) code to have something like this in every app because it defeats the purpose:
#if DEBUG
Foo.IsDebug = true;
#endif
UPDATE: Clarification for why I want that: I want to enable Debug codes (i.e enable WebView debug signal) if the calling app is in in development and don't want such code to exist in final view. That's why I am interested in a solution that prevent such code leaking to Release build.
Upvotes: 1
Views: 1301
Reputation: 20658
Thanks to the comments and answers, I've found two working solutions, both are great but I think I will use Conditional
in my final project. IsExecutingDebug
checks if DebuggableAttribute
is present in the Entry assembly, while Conditional
is explained in Jon Skeet's answer.
namespace ClassLibrary1
{
public class Class1
{
public bool IsExecutingDebug()
{
#if DEBUG
Console.WriteLine("Debug in lib");
#endif
return Assembly.GetExecutingAssembly().IsInDebug();
}
[Conditional("DEBUG")]
public void ExecuteInDebugOnly()
{
Console.WriteLine("Hi!");
}
}
}
namespace System
{
public static class MyExtensions
{
public static bool IsInDebug(this Assembly assembly)
{
return assembly.GetCustomAttributes<DebuggableAttribute>().Any();
}
}
}
Upvotes: 0
Reputation: 1500385
You can use Conditional
in Foo
to decorate a method - any calls to that method will depend on whether the calling code defines the relevant symbol. So something like:
[Conditional("DEBUG")]
public void MaybeSetDebugMode()
{
// Remember the decision
}
Then the calling code can unconditionally write code calling MaybeSetDebugMode
, and the call will only actually be compiled in if DEBUG
is defined when the calling code is compiled. The method in Foo
itself will be compiled into Foo.dll
regardless of the symbols defined when you compile it.
That's not the same as #if
, which does depend on the symbols when you're compiling your code.
Note that this is how Debug.WriteLine
etc work.
One downside of this: this code absolutely will exist in the "final build" unless you take more action. It has to, given that the existence of code in Foo.dll can't change depending on what calls it.
So you may actually want to use #if
instead, for example:
#if FINAL_BUILD
public void MaybeSetDebugMode()
{
// This method exists so that the calling code will still build
// with the final DLL, but there won't be any "interesting" code
// for anyone to find.
}
#else
public void MaybeSetDebugMode()
{
// Interesting code goes here. This code won't be included in the final build,
// but callers can call it unconditionally, because there'll be an empty
// method in the final build.
}
#endif
Upvotes: 4