Is it possible in .Net to call some code only from the debug builds of client assemblies?
I am writing a (very small) structure to test the pre- and postconditions of methods. Entry points (they can be easily accessed, it doesn't matter):
public static class Ensures {
public static Validation That {
get { ... }
}
}
public static class Requires {
public static Validation That {
get { ... }
}
}
Obviously, checking postconditions can be expensive and really unnecessary when the method is not an error. So I need a method that works like this:
public static class Ensures {
[ConditionalCallingCode("DEBUG")]
public static Validation ThatDuringDebug {
get { ... }
}
}
where ConditionalCallingCodeAttribute
means that this method should only be executed when the calling code is compiled with a specific DEBUG symbol. Is it possible?
I want the client code to look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
Ensures.WhileDebuggingThat // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
return result;
}
}
Of course, I just can't provide WhileDebuggingThat. Then the client code will look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
#ifdef DEBUG
Ensures.That // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
#endif
return result;
}
}
This is a backup plan if all else fails, but it severely violates DRY.
As I understand it, marking WhileDebuggingThat
with [Conditional("DEBUG")]
will emit (or not) this method depending on whether DEBUG is defined at compile time of the library, rather than from the collections that reference that library. So I could do that and then write documentation telling library users to link the debug assemblies of their code to the debug build of the library and release assemblies with the assembly versions. This does not affect me as the best solution.
Finally, I can tell the library users to define this class inside their projects:
using ValidationLibrary;
public static class EnsuresWhileDebugging {
[Conditional("DEBUG")]
public static Validation That() {
return Ensures.That;
}
}
This should work just as far as I can see, but still requires a DRY violation, if only a little.
source to share
Any solution found here will be slower than the actual checks. Also, since it won't be built into the compiler, for example ConditionalAttribute
, the parameters will still be computed. If postconditions can be very complex like
Ensures.That.IsPositive(ExpensiveCalculation(result));
You might consider using icelava's suggestion to reflect on the calling assembly to find if it is built in debug or release - but then you have to use some kind of delegate to delay the computation - to make sure it is only executed then. when it is necessary. eg:.
Ensures.WhileDebugging.That. IsPositive(() => ExpensiveCalculation(result));
The IsPositive function should run the lambda and check its result only after reflection to see if it should be evaluated.
source to share
Is this something the normal ConditionalAttribute doesn't do for you, besides working on a property instead of a method? You may need to change the way you call it so that you have methods instead of properties, and the fact that it returns a value can cause problems.
It would be very helpful if you could demonstrate how your framework is used - we currently have no one to work with.
Another thing to consider would be supplying different binaries of your library - so that the caller can just provide a different version that doesn't actually do any checks. Again, it's hard to tell with just the code you provided.
source to share
I have not tried this since I am going to swim and leave the house.
- Call Assembly.GetCallingAssembly () to get the assembly that the method (class) that calls your currently executing method comes in.
- Check the Assembly object to see if it is a Release or Debug assembly .
source to share
It looks like most of what you are doing is already covered with help Debug.Assert()
.
In this case, this code will only work in debug mode (but you have to put up with the slowness of the blocking):
try
{
Debug.Assert(false);
}
catch (Exception e)
{
// will only and always run in debug mode
}
source to share
I'm not sure, but I think you could use ConditionalAttribute to do this: whether to emit a call or not will depend on the user's assembly type, not your library. You can check this with Reflector or ILDasm: compile your samples and in Reflector (ILDasm) see if the call is being called in the sample project.
source to share
I have this happening: Project. Call 1 function B. B include this function: Assembly.GetCallingAssembly (). FullName If build B is in debug then running mode, this function returns the name of Project A if build at release mode than the checkout name of project B. I don't know why this is happening. Please support me Thanks