Notes from Daily Encounters with Technology RSS 2.0
 
# Monday, September 1, 2014

Let’s take a closer look at the following static class:

public static readonly string Field = "Static value";

static StaticClass()
{
  Debug.WriteLine("Static constructor called.");
}

Up until today I was convinced, that given such a class the following couldn’t happen:

StaticClass.Field = null

Obviously I was wrong: the static readonly field with an initializer is uninitialized. Of course this required closer examination.

We’ll start with the language specification. This is being said about static field initialization in section 10.5.5.1:

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

The above class has a static constructor, therefore the following text about static constructors is also relevant (section 10.12):

The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • An instance of the class type is created.
  • Any of the static members of the class type are referenced.

Still, no matter what you do, the field initializer should execute before it is accessed for the first time, hence it should never have null value. The above image proves this wrong. We need some more code to get to the bottom of this:

static void Main(string[] args)
{
  Debug.WriteLine("Field value: " + StaticClass.Field);
}

Now let’s a put a breakpoint before the only line of code is executed and after it. Once the first breakpoint is hit, we can take a look at StaticClass from Immediate Window:

StaticClass
ConsoleApplication2.StaticClass
    base: object
    Field: null

Field is not initialized yet. This doesn’t affect the code execution, though. As soon as we run the program to the second breakpoint, we get the following in the output window:

Static constructor called.
Field value: Static value

Repeating the same call in Immediate Window now also gives the expected result:

StaticClass
ConsoleApplication2.StaticClass
    base: object
    Field: "Static value"

As it seems, looking up the field value in debugger doesn’t have any side effects - no code gets executed, unlike when accessing properties. But that’s already a subject for another post about bad software development practices.

Monday, September 1, 2014 6:05:59 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | C#
# Monday, August 25, 2014

Recently I set up multiple different configurations for my ASP.NET project with different .config file transformations for different environments. After I started switching between them on a regular basis, the following build error started showing up every time I changed to a different configuration:

...\obj\debug\web.config(40): error ASPCONFIG: It is an error to use a section 
registered as allowDefinition='MachineToApplication' beyond application level.
This error can be caused by a virtual directory not being configured 
as an application in IIS.

As you can see the error points to the web.config file inside obj folder. It always belonged to a configuration which I was building before switching to the current one. The issue could of course be resolved by manually deleting the offending file, but I soon got tired of this and decided to investigate further.

I quickly noticed that the problem was limited to the ASP.NET MVC project only. The other web project in the solution, hosting a WCF web service also contained multiple configurations, but there were no build errors after switching between them. This was finally enough information to find that others were already writing about it. It turned out that the problem would go away if I disabled building of views by removing the following property from the project file:

<MvcBuildViews>true</MvcBuildViews>

By disabling this feature I would loose the build time check of view validity against their current models, therefore I didn’t want to do it and had to find a different solution. In the end I settled with just deleting the problematic files inside the obj folder before each build, by adding the following command to the ASP.NET MVC project pre-build event:

del "$(ProjectDir)obj\*.*" /s /q

I could have deleted just the web.config files, but this would mean having a delete command for each configuration and also remembering to add another command each time a new configuration was added. Since files in obj folder are regenerated each time any way, this seemed a more pragmatic solution.

Monday, August 25, 2014 6:48:13 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback

# Monday, August 18, 2014

Static code analysis is a very useful feature of ReSharper. The generated warnings can help you fix bugs which might otherwise remain unnoticed. Look at the following code:

Loop control variable is never changed inside loop

Do you see the issue? You would definitely have a more difficult time noticing it, if ReSharper didn’t warn you about it: Loop control variable is never changed inside loop. It might even remain unnoticed when surrounded by all the other code.

Unfortunately static analysis is not perfect and it might detect false positives - warning you about potential issues in code, which in reality aren’t issues at all. Let’s take a look at another example:

Access to disposed closure

ReSharper’s warning in this case: Access to disposed closure. The reason being: this code could fail if ExceptionAssert.Throws would store the lambda and execute it after scope was already disposed. Looking at its code, we can see, this is not the case:

public static T Throws<T>(Action action)
   where T : Exception
{
   try
   {
      action();
   }
   catch (T exception)
   {
      return exception;
   }
   Assert.Fail("No {0} was thrown.", typeof(T).FullName);
   return null;
}

The lambda is not being stored and is executed before the method completes, i.e. this ReSharper’s warning is a false positive.

There are a couple of ways to tell ReSharper about it, so that it doesn’t warn us any more. The simplest one is being offered as a quick fix: the check can be disabled with a special comment:

Disabling a warning with a comment

Although this works, it’s not a perfect solution since you need to add such a comment every time you call ExceptionAssert.Throws by passing it an IDisposable.

When we know that it’s always safe to pass an IDisposable to our method, we can tell that to ReSharper using its annotation attributes:

public static T Throws<T>([InstantHandle]Action action)
   where T : Exception
{
   try
   {
      action();
   }
   catch (T exception)
   {
      return exception;
   }
   Assert.Fail("No {0} was thrown.", typeof(T).FullName);
   return null;
}

This way we permanently got rid of the warning and the comment is not needed any more:

Disabling a warning with code annotations

To use the annotations, you either need to reference ReSharper’s JetBrains.Annotations.dll assembly or define the annotation attribute classes directly in your code. Unfortunately there’s no official NuGet package for either, but there’s plenty of unofficial options available. To my experience, it doesn’t really matter which one you choose, they all seem to achieve their goal just fine: you don’t need to reference an assembly from a proprietary location in your project or put it in source control.

The above of course only works when you have access to the source code. When you don’t, but you’d still like to improve ReSharper’s static code analysis, you can use external annotations. That’s how ReSharper’s authors have annotated the framework assemblies for you.

Monday, August 18, 2014 6:37:37 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | C# | Software | ReSharper | VisualStudio
# Thursday, August 14, 2014

After first hearing about C# Tips by Jason Roberts in a tweet less than a month ago, I decided to buy it and see whether the author can really contribute to writing better C# as he promises on the book’s web page. After reading it, I can agree.

As the title says, most of the book is dedicated to short tips and tricks on how to make the most of the language and improve your code. Currently there are 21 tips in the book and based on your previous experience you might already know about some of them. Still, I’m pretty sure, you’re going to learn at least something new. I must say, I wasn’t aware of all the nuances described in the book, although I’ve been using C# on almost daily bases since it was first released. And even for things you already know, it’s sometimes good to be reminded again.

The remaining two parts of the book; I didn’t like that much. Both design patterns and unit testing deserve more attention and you’re better of learning about them from dedicated books. Well, for those who will first hear about them here, it might be just enough to make them buy another book on the subject.

Nevertheless, the book is definitely worth getting. The author is letting the readers decide for themselves how much they think its worth and set their own price. Since this can be difficult based just on the info on the page, maybe this review can help you set the right price. I certainly don’t regret buying the book and I’m looking forward to it being completed. The author seems to be updating it regularly.

Thursday, August 14, 2014 6:44:31 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | C# | Reviews
# Monday, August 11, 2014

One of the more attractive parts of Workflow Foundation is its workflow designer and the possibility of rehosting it in your own application with a minimum amount of code. Often simple rehosting of the designer is enough, but sometimes you will want to do some additional background processing of the workflow as the user is designing it. Here are a couple of ideas for such processing:

  • Ensure that each activity has a unique display name. In case of a duplicate display name append a sequential number to it (e.g. Sequence, Sequence 1, sequence 2, etc.).
  • Some custom activities require the designer to provide them with additional information, such as a list of valid values for a property in the current context. For this purpose they can expose a property, which the designer will set to a proxy data access class.

All such features require a traversal of all activities in the workflow. In this article I’m going to present a way for achieving that, implementing a simplified version of the first idea in the process: set the display name of each newly added activity to a random Guid value.

We first need to attach a handler to the designer’s ModelChanged event:

private void AddDesigner()
{
  //Create an instance of WorkflowDesigner class.
  this.wd = new WorkflowDesigner();

  //Place the designer canvas in the middle column of the grid.
  Grid.SetColumn(this.wd.View, 1);
  
  //Load a new Sequence as default.
  this.wd.Load(new Sequence());

  //Add the designer canvas to the grid.
  grid1.Children.Add(this.wd.View);

  //Attach the event handler
  var modelService = wd.Context.Services.GetService<ModelService>();
  modelService.ModelChanged += OnModelChanged;
}

The above code is based on the method from MSDN’s designer hosting tutorial.

In .NET 4.5 the only property of ModelChangedEventArgs that should be used, is ModelChangeInfo. In .NET 4 separate ItemsAdded, ItemsRemoved and PropertiesChanged properties are available instead, which are now marked as obsolete. The key to processing the changes is ModelChangeInfo.ModelChangeType. Based on it different types of changes can be handled in a different way.

In our scenario we only need to traverse newly added activities, therefore the only ModelChangeTypes of interest to us are CollectionItemAdded and PropertyChanged:

private void OnModelChanged(object sender, ModelChangedEventArgs e)
{
  switch (e.ModelChangeInfo.ModelChangeType)
  {
    case ModelChangeType.CollectionItemAdded:
    case ModelChangeType.PropertyChanged:
      RandomizeDisplayName(e.ModelChangeInfo.Value);
      break;
  }
}

In a naive first attempt we will search for the DisplayName property of the changed item and set it to the desired value:

private void RandomizeDisplayName(ModelItem item)
{
  if (item == null)
  {
    return;
  }

  var displayNameProperty = item.Properties
    .SingleOrDefault(property => property.Name == "DisplayName");

  if (displayNameProperty != null)
  {
    displayNameProperty.SetValue(Guid.NewGuid().ToString());
  }
}

This would work as long as the user would only add individual activities from the toolbox. Though, the designer also supports pasting of composite activities, e.g. a Sequence with multiple activities inside it. The above code would only set the display name of the root activity in such a case. To also process all its sub-activities, we need to recursively traverse the activity tree:

private void RandomizeDisplayName(ModelItem rootItem)
{
  if (rootItem == null)
  {
    return;
  }

  var displayNameProperty = rootItem.Properties
    .SingleOrDefault(property => property.Name == "DisplayName");

  if (displayNameProperty != null)
  {
    displayNameProperty.SetValue(Guid.NewGuid().ToString());
  }

  foreach (var modelProperty in rootItem.Properties)
  {
    if (typeof(Activity).IsAssignableFrom(modelProperty.PropertyType) ||
      typeof(FlowNode).IsAssignableFrom(modelProperty.PropertyType))
    {
      RandomizeDisplayName(modelProperty.Value);
    }
    else if (modelProperty.PropertyType.IsGenericType && 
      modelProperty.PropertyType.GetGenericTypeDefinition() == typeof(Collection<>) &&
      modelProperty.Collection != null)
    {
      foreach (var activityModel in modelProperty.Collection)
      {
        RandomizeDisplayName(activityModel);
      }
    }
  }
}

If you take a closer look at the above foreach loop, you can see that it only processes the Activity (e.g. branches of If activity) and FlowNode (a node inside a FlowChart) properties, and enumerates all collection properties (e.g. FlowChart Nodes or Sequence Activities).

This is already enough for our sample scenario, but since activity traversal will probably be a common operation in the hosted designer, we can refactor the above code for activity enumeration so that it can be used for any activity processing:

private void ProcessActivities(ModelItem rootItem, Action<ModelItem> action)
{
  if (rootItem == null)
  {
    return;
  }

  action(rootItem);

  foreach (var modelProperty in rootItem.Properties)
  {
    if (typeof(Activity).IsAssignableFrom(modelProperty.PropertyType) ||
      typeof(FlowNode).IsAssignableFrom(modelProperty.PropertyType))
    {
      ProcessActivities(modelProperty.Value, action);
    }
    else if (modelProperty.PropertyType.IsGenericType && 
      modelProperty.PropertyType.GetGenericTypeDefinition() == typeof(Collection<>) &&
      modelProperty.Collection != null)
    {
      foreach (var activityModel in modelProperty.Collection)
      {
        ProcessActivities(activityModel, action);
      }
    }
  }
}

The action to be performed on each activity can now be implemented in a separate method:

private void RandomizeDisplayName(ModelItem item)
{
  var displayNameProperty = item.Properties
    .SingleOrDefault(property => property.Name == "DisplayName");

  if (displayNameProperty != null)
  {
    displayNameProperty.SetValue(Guid.NewGuid().ToString());
  }
}

To do the processing, we can call the common traversal method, passing it the above implemented action:

private void OnModelChanged(object sender, ModelChangedEventArgs e)
{
  switch (e.ModelChangeInfo.ModelChangeType)
  {
    case ModelChangeType.CollectionItemAdded:
    case ModelChangeType.PropertyChanged:
      ProcessActivities(e.ModelChangeInfo.Value, RandomizeDisplayName);
      break;
  }
}

We now only have to implement a different action and pass it to ProcessActivities, to process them in a different way. No need to worry, how to actually enumerate all the sub-activities.

Monday, August 11, 2014 6:33:03 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | WF4
My Book

NuGet 2 Essentials

About Me
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2014, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.