I have the following method:
private void DoSomething(CoolClass coolClass)
{
if (coolClass == null)
{
throw new ArgumentNullException("coolClass");
}
coolClass.Name = "Pepe";
}
With Code Contracts we can write it like this:
private void DoSomething(CoolClass coolClass)
{
Contract.Requires<ArgumentNullException>(coolClass != null, "IS NULLL!");
coolClass.Name = "Pepe";
}
The second method is shorter and simpler. The problem that I have is that when you build it, in runtime it does not throw the exception, it shows this:
Description: An assembly (probably "CodeContractsTest") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.Requires and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. After the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL.
Unless with VS you download the CodeContracts for .net from here.
And then you check the "Runtime check" in the project, so that when you build it in runtime, the exception is thrown.
Our app is build with Jenkins with PowerShell scripts. Is there any way to check in runtime and throw the exception, with a simple command or attribute, or something easy?
By changing following project properties I could eliminate getting this exception while running.
Right click on project -> Properties -> Code Contract (Tab)
change the assembley mode to "Standard Contract Requires" also select checkbox - Perform Runtime contract checking
Why don't you just write your own version of the method, if you like the simplicity?
public class CustomContract
{
public static void Requires<TException>( bool Predicate, string Message )
where TException : Exception, new()
{
if ( !Predicate )
{
Debug.WriteLine( Message );
throw new TException();
}
}
}
Using Code Contracts just to have a friendly API sounds like shooting sparrows with a cannon.
Related
In the aspnet-api-versioning I have found out a codeblock:
DefaultApiControllerFilter( IEnumerable<IApiControllerSpecification> pecifications )
{
Arg.NotNull( specifications, nameof( specifications ) );
this.specifications = specifications.ToArray();
}
The interested block is Arg.NotNull( value, "text" ); from the Microsoft namespace.
And there are several similar asserts in the code. Another example is Contract.Requires() from System.Diagnostics.Contracts
Tried to search over Microsoft docs about work principles but didn't found info.
So maybe could help to find out how does it work: like postsharp code rewrite, provide runtime conditional check as Debug.Assert or maybe simply throws exceptions(but it doesn't mention in docs)?
They are code contracts (see https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts and https://www.microsoft.com/en-us/research/project/code-contracts/?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fprojects%2Fcontracts%2Fuserdoc.pdf)
Unfortunately they didn't really take off and the project was kind of abandoned, which is a shame as they had potential.
After downloading library sources, compile and get look through compiled code found out that Microsoft::Arg is just a shared code project with a method
internal static void NotNull<T>(T value, string name) where T : class
{
if ((object) value == null) throw new ArgumentNullException(name);
}
and the Contract.Requires(condition) is an Code Contract Assert codegenration extension which ...doesn't produce any code becuse of absence of the assert post build event. The similar sutuation on stackowerflow .
Suppose a Visual Studio project ProjectA.SampleClass that has a method wrapped inside #if DEBUG ... #endif symbols, i.e. the method will only be included in Debug builds:
public class SampleClass
{
...
#if DEBUG
public void ConditionalMethod() { ... }
#endif
}
Another project, ProjectB, calls SampleClass.ConditionalMethod(), but obviously it can only do successfully if ProjectA defines a DEBUG constant.
Is there a built-in way to check in ProjectB, at compile time, if ProjectA has the DEBUG constant defined? Something like this:
#if ProjectA.DEBUG
ProjectA.SampleClass.ConditionalMethod();
#endif
I can think of some obscure AOP ways to achieve something like this with post-compilation IL editing, but that's not very desirable.
Try with new build configuration configuration. Go to solution right click and select Configuration Manager. From here define new configuration. After that make sure that you new configuration is selected and you will see how the column Configuration for each project is set to the new configuration. If not - select it. Then define the symbols that you want for each project.
A better design would probably be to define the method either way, and have one of the methods simply be a no-op:
#if DEBUG
public void ConditionalMethod() { ... }
#else
public void ConditionalMethod() {} // Method does nothing
#endif
(You could also simply place the #if/#endif around the body of the method, of course.)
Then Project B can call the method regardless, with its behavior changing depending on how Project A was compiled.
I have an postsharp attribute for handling exceptions in a entire dll ( that ddl is provided by other team) and manage database calls.
So the idea is treat the exceptions with postsharp
So, this is the attribute
[Serializable]
public class MethodConnectionTracking: OnExceptionAspect
{
bool canceled = false;
public override void OnException(MethodExecutionArgs args)
{
Exception ex = args.Exception;
if (ex != null)
{
--- do things
}
}
}
to make that works and intercept all methods in the assemblyInfo.cs for that project called SPData i have:
[assembly: MethodConnectionTracking(AttributeTargetElements = MulticastTargets.Method)]
and that works great. But i want to specify that line in other project.
So, the main project references SPData. So, in main project AssemblyInfo.cs file i write:
[assembly: MethodConnectionTracking(AttributeTargetAssemblies = "SPData", AttributeTargetElements = MulticastTargets.Method)]
But it does not work.
Is it possibly to do what i want, Am I missing some parameter?
Thanks in advance.
You don't need AttributeTargetElements = MulticastTargets.Method as it is already provided when using OnExceptionAspect base class
You don't need to check if ex != null because it will never be null as OnException won't be invoked unless there is an exception. See http://programmersunlimited.wordpress.com/2011/08/01/postsharp-why-are-my-arguments-null/
Are you sure you have the correct assembly name? Are you using the namespace? You need to use the actual assembly name (without the .dll). Try a wildcard "SPData*" and see if that helps.
Have you stepped through the code or looked at the compiled assembly using ILSpy? Unless you are providing the wrong name, it should work. Is the reference to a project or a compiled assembly? Is the assembly signed or obfuscated?
I am attempting to deploy my first alpha version of a system online for a few people to start using. On development I make heavy use of the DropCreateDatabaseOnModelChange<TContext> (I don't have it in front of me at the moment so I can't verify the exact name) to re-initialize my dev database every time my model changes. This happens in the Global.asax.
However, I do not want this to happen on my web host where other people are entering real data. I need to handle all db migrations on there myself so data is preserved.
I had considered #ifdef DEBUG tags to prevent the database initializer from being called, but I don't like that solution. Right now, I have the debug version deployed, so if they come across any errors it is easy for me to see and debug them (this is very very alpha, so only a select few people are using it and know to expect errors).
What other options do I have to prevent Prod DB dropping by EF4 code first?
What about inversion of control:
var initializer = container.Resolve<IDatabaseInitializer<Context>>();
Database.SetInitializer(initializer);
Based on your IoC configuration you will either return developement or production initializer. You can have different configuration file for each build configuration so you can also have IoC container configured differently.
public class ThrowExceptionInitializer : IDatabaseInitializer<Context>
{
public InitializeDatabase(Context context)
{
// Custom exception
throw new InvalidVersionException("The new application version is not supported by the database version");
}
}
As #Johann says, the ConditionalAttribute is probably the cleanes solution here:
[Conditional("DEBUG")]
private void InitializeDb()
{
// Initializer code here
// DropCreateDatabaseOnModelChange<TContext>
}
and in Global.asax:
public void Application_Start // or wherever it is you're initializing
{
// This will only be called if the DEBUG constant is defined
InitializeDb();
}
You can always create a new Configuration (in addition to Debug and Release). You would then define a Conditional Compilation Symbol for the new configuration. For example if I created a new configuration called LocalDebug (with the same settings at the default debug) I would then add LOCALDEBUG to the Conditional Compilation Symbols. With this defined you can use:
#if LOCALDEBUG
//do database stuff
#endif
Then you can still deploy the built in debug configuration and this section will not fire.
You could use the Conditional attribute but it is not so different from the #ifdef
If you are using sql express in development and not on your production box you can filter by the connection.
protected void Application_Start(object sender, EventArgs e)
{
using (var db = new MyDb())
{
if (db.Database.Connection.DataSource.IndexOf("sqlexpress", StringComparison.InvariantCultureIgnoreCase) > -1)
{
Database.SetInitializer(new MyDbInitializer());
}
}
}
The trusty old preprocessor directive in C# appear to work great when I write:
#if DEBUG
...
(Some code)
...
#endif
However, attributes enclosed in the conditional block appear to continue to get processed and I get errors indicating such. For instance, surrounding an [AssemblyVersion(...)] within the conditional block appears to have no affect.
I can go into the details as to why we want to conditionally ignore the [AssemblyVersion(..)], but it's irrelevant. Any ideas?
This works correctly for me. In my AssemblyInfo.cs file, I have the following:
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
Looking at the compiled assembly in Reflector, I see the correct attributes.
You should make sure that your DEBUG symbol is only defined in the project properties and not any where else in your code as an actual #define DEBUG instruction. If you have it defined directly in code it will only be in effect for that file, not the entire project. Defining it in the project properties will cause it be in effect for the entire project.
I figured it out! There was a key piece of information I neglected to mention: that it was a Workflow project (Guid {14822709-B5A1-4724-98CA-57A101D1B079}). It turns out that there is a bug with the workflow project type, specifically the Workflow.Targets file that is included in the build file.
It appears that the preprocessor acts as though the DEBUG constant is defined. You can repro the issue by creating a workflow project and adding this to the AssemblyInfo file:
#if DEBUG
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
Then try a release build.
I filed this with MS: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466440
Best regards!
-Sean
Are you sure you're not building in release mode?
simpler - you can tag your debug function(s) with the metadata tag [Conditional]:
#define DEBUG1
...
public static void PrintText1(string txt) {
Console.Write("This is PrintText2\n");
}
[Conditional("DEBUG1")]
public static void PrintText2(string txt) {
Console.Write("This is PrintText2\n");
}
[STAThread]
static void Main(string[] args) {
PrintText1("This is the unconditional method");
PrintText2("This function will be called only if 'DEBUG1' is defined");
}
try it!
Also, what I noticed is that #define only exists within the context of the file it is defined, ex calling PrintText2 from another file, where debug is not defined, will not execute. This also works the other way around:
[Conditional("DEBUG1")]
public static void ConditionedPrint(string txt) {
Console.Write("This is PrintText2\n");
}
public static void UnconditionedPrint(string txt) {
ConditionedFunc(txt);
}
UnconditionedFunc will print "This is PrintText2\n" iff (if and only if) #define DEBUG1 was defined in this file, regardless of the other files.
There is also System.Diagnostics.Debug, I'm not sure what it does though.
To follow up #yoyoyoyosef comment answer, you need to check the Properties page of your Project.
You will see in the Build menu, under the General heading, make sure the "Define DEBUG constant" checkbox is not checked.
This value changes based upon the "Configuration" choice (dropdown) at the top of the Build menu.