Using PostSharp.Toolkit.Diagnostics, when not all developers have Pro licenses.

We have only couple of developers who are using PostSharp.Toolkit.Diagnostics and having  PostSharp Pro license .
However ther are much more developers , who are building our solution, but do not required Toolkit.Diagnostics XmlMulticast features, that are referred in %ProjName%.psproj file.
 
As a workaround I’ve suggested to to replace locally psproj file with dummy, that doesn’t have XmlMulticast(PostSharp feature that available only in Pro edition).
 
If a developer doesn’t have PostSharp Pro license, they shoul set  Environment variable POSTSHARP_PRO=false to effectively exclude psproj from the build on their local machine.
detailed instructions How to Add, Remove or Edit Environment variables in Windows 7 can be found at http://www.itechtalk.com/thread3595.html.
For Each project using PostSharp.Toolkit.Diagnostics  A subfolder PreBuild.Config has been created.
It includes minimal dev.psproj ,
PreBuild.cmd
and the full %ProjName%.psproj (e.g. MyProject.psproj ) that is used as a master version on build machine.
 

%ProjName%.psproj located in the root on local machines should kept  as minimal – the same as Dev.Configdev.psproj.

 

<?xml version=1.0 encoding=utf-8?>

<!–Empty project for developers without PostSharp Pro.

       Do NOT check-in   %ProjName%.psproj

       –>

       <Project xmlns=http://schemas.postsharp.org/1.0/configuration ReferenceDirectory={$ReferenceDirectory}>

              <Property Name=LoggingBackEnd Value=nlog />

              <Using File=default />

              <Tasks>

              </Tasks>

 

</Project>
 
For each project that uses toolkit insert into PreBuild Event command line
cmd /c $(ProjectDir)PreBuild.Config\PreBuild.cmd $(ProjectName)
 
File PreBuild.Config\PreBuild.cmd
rem developers without PostSharp Pro installed please set environment variable POSTSHARP_PRO=false
@rem see http://www.itechtalk.com/thread3595.html detailed instructions How to Add, Remove or Edit Environment variables in Windows 7
@REM Insert into PreBuild Event command line
@REM cmd /c $(ProjectDir)\PreBuild.Config\PreBuild.cmd $(ProjectName)
set ProjName=%1
set PSProjFile=..\%ProjName%.psproj
if ‘%POSTSHARP_PRO%==’false goto devPsproj
:proPsproj
set FileFrom=%ProjName%.psproj
@goto copyFile
:devPsproj
set FileFrom=dev.psproj
:copyFile
rem The current dir seems to be \bin\Debug for Library project or Windows Console/Services, but \bin for WAP(Webjet application project)
cd ..\..\PreBuild.Config

ATTRIB -R %PSProjFile%
copy /Y %FileFrom% %PSProjFile%
:end
@rem pause

VAB ValidationResults Extensions

We’ve started to actively used Microsoft Enterprise Library Validation Enterprise Block ( VAB)  and I was surprised , that a few commonly used  operations are not supplied(or I haven’t found them) out of the box.
See two extensions, that make use of VAB simpler

public static class ValidationResultsExtensions
       {
               public static string CombinedMessage( this ValidationResults results)
              {
                      string errorMessage = ( from res in results select String.Format( {0}:{1} , res.Key, res.Message)).ToDelimitedString( “;”);
                      return errorMessage;
              }
//Throws ValidationException if not valid
           public static void ValidateConstraints<T>( this T target)
           {
               Validator validator = ValidationFactory.CreateValidator<T>();
               var results = new ValidationResults();
               validator.Validate(target, results);
               if (results.IsValid == false)
               {
                   var errorMessage = results.CombinedMessage();
                   throw new ValidationException(errorMessage);
               }
           }
       }v

Using CollectionNotEmptyValidator

We recently started to use Microsoft Enterprise Library Validation Enterprise Block
 (VAB) to check interfaces between modules. One of the properties to validate is array  
of values, that should be not empty, and shoul include one of expected values. 
I found CollectionNotEmptyValidator at http://www.eggheadcafe.com/tutorials/xaml/9af7ac1a-d7f3-4e00-9aec-33ef1ec7d1a3/wpf-custom-validation-using-the-enterprise-library.aspx, that allows to  validate the property to satisfy part of requirements.
 
The class mostly works as is, I’ve only changed exception to Validation error if object to validate is not a collection.

        public override void DoValidate( object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
              {

                      if (objectToValidate is ICollection)
                     {

                            if (((( ICollection)objectToValidate).Count != 0) == Negated)
                           {

                                  LogValidationResult(validationResults, MessageTemplate, currentTarget, key);

                           }

                     }

                     else
                     {

//throw new ApplicationException(“Object type not supported by validator.”);

                           LogValidationResult(validationResults, “Object is not a collection.”, currentTarget, key);
                     }

I’ve also changed testing console app to a number of MSTest TestMethods.

#region Namespace Imports
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.SDC.Common.Validation;
using Microsoft.SDC.Common.Web.WCF;
using Microsoft.VisualStudio.TestTools.UnitTesting;


#endregion
namespace MSCommon.Validation
{
// I have defined an Order class
//      containing an Items property for this. There are four possible cases we can test:


//- Collection is empty, Negated property is false

//- Collection is non-empty, Negated property is false

//- Collection is non-empty, Negated property is true

//- Collection is empty, Negated property is true


       [ TestClass]
        public class CollectionNotEmptyValidatorTests
       {
              [ TestMethod(), CITest ]
               public void InvalidTest_CollectionIsEmpty()
              {
                      // Invalid test – collection is empty
                      var order = NewEmptyOrder();
                      CollectionNotEmptyValidator validator = new CollectionNotEmptyValidator ();

                      ValidationResults results = validator.Validate(order.Items);

                      Assert.IsTrue(!results.IsValid);

                      Debug.WriteLine(results.First().Message);

                      // Output: The collection must not be empty.
              }

              [ TestMethod(), CITest ]
               public void ValidTest_CollectionIsEmpty()
              {
                      // Valid test – collection has items
                      var order = NewEmptyOrder();
                     order.Items.Add( new Order. OrderItem());
                      CollectionNotEmptyValidator validator = new CollectionNotEmptyValidator ();

                      ValidationResults results = validator.Validate(order.Items);

                      Assert.IsTrue(results.IsValid);

                      Debug.WriteLine( “Valid test”);
              }

              [ TestMethod(), CITest ]
               public void NegatedTest_CollectionHasItems()
              {
                      // Invalid test – collection has items (Negated)

                      var order = NewEmptyOrder();
                     order.Items.Add( new Order. OrderItem());
                      CollectionNotEmptyValidator validator = new CollectionNotEmptyValidator (true );

                      ValidationResults results = validator.Validate(order.Items);
                      Assert.IsTrue(!results.IsValid);

                      Debug.WriteLine(results.First().Message);
                      // Output: The collection must be empty.
              }


              [ TestMethod(), CITest ]
               public void NegatedTest_CollectionIsEmpty()
              {
                      // Invalid test – collection has items (Negated)

                      var order = NewEmptyOrder();
                     order.Items.Add( new Order. OrderItem());
                      CollectionNotEmptyValidator validator = new CollectionNotEmptyValidator (true );

                      ValidationResults results = validator.Validate(order.Items);
                      Assert.IsTrue(!results.IsValid);

                      Debug.WriteLine(results.First().Message);
                      // Output: The collection must be empty.
              }


               private static Order NewEmptyOrder()
              {
                      Order order = new Order();

                     order.Items = new Collection<Order .OrderItem >();
                      return order;
              }

              #region Example Classes for tests

               public class Order

              {
                     [ CollectionNotEmptyValidator()]
                      public Collection<OrderItem > Items { get; set; }

                      public bool ValidateItems()

                     {
                            return Items.Count > 0;
                     }

                      public class OrderItem

                     {
                     }
              }

              #endregion //Example Classes for tests
       }
}
I am planning to create derived ContainValidator.

Do NOT Change “Copy Local” project references to false, unless understand subsequences.

To optimize performance of visual studio build I’ve found multiple recommendations to change CopyLocal property for dependent dlls to false,
  1. e.g. From http://stackoverflow.com/questions/690033/best-practices-for-large-solutions-in-visual-studio-2008 
  • CopyLocal? For sure turn this off
  • Always set the Copy Local property to false and enforce this via a custom msbuild step
  • My advice is to always set ‘Copy Local’ to false

Some time ago we’ve tried to change the setting to false, and found that it causes problem for deployment of top-level projects.

Recently I’ve followed the suggestion and changed the settings for middle-level projects. It didn’t cause immediate issues, but I was warned by Readify consultant colin savage about possible errors during deployments.

I haven’t undone the changes immediately and we found a few issues during testing.

There are many scenarios, when you need to have Copy Local’ left to True.

The concerns are highlighted in some StackOverflow answers, but they have small number of votes.The concerns are highlighted in some StackOverflow answers, but they have small number of votes.

 

Top-level projects:  set copy local = true.

First of all, it doesn’t work correctly for top-level projects, i.e. executables or web sites.
  • for all the references in the one at the top set copy local = true.
If you set ‘ Copy Local = false’, VS will, unless you tell it otherwise, place each assembly alone in its own .binDebugdirectory. Because of this, you will need to configure VS to place assemblies together in the same directory. To do so, for each VS project, go to VS > Project Properties > Build tab > Output path, and set the Ouput path to ..binDebugfor debug configuration, and ..binRelease for release configuration.
 

Second-level  dependencies:  set copy local = true.

 

Another example when copylocal =false fails on run-time, is when top level assembly doesn’t directly referenced one of indirect dependencies.
E..g. Top-level assembly A has reference to assembly B with copylocal =true, but assembly B has reference to assembly C with copylocal =false. Most likely assembly C will be missing on runtime and will cause errors 

 
Copy local is important for deployment scenarios and tools. As a general rule you should use CopyLocal=True

and http://stackoverflow.com/questions/602765/when-should-copy-local-be-set-to-true-and-when-should-it-not?lq=1

Unfortunately there are some quirks and CopyLocal won’t necessary work as expected for assembly references in secondary assemblies structured as shown below.

  • MainApp.exe
  • MyLibrary.dll
  • ThirdPartyLibrary.dll (if in the GAC CopyLocal won’t copy to MainApp bin folder)

This makes xcopy deployments difficult . 

Reflection called DLLs  dependencies:  set copy local = true.
E.g user can see error “ISystem.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.”

The fix for the issue is recommended in http://stackoverflow.com/a/6200173/52277

“I solved this issue by setting the Copy Local attribute of my project’s references to true.”

 

In general, the problems with investigation of deployment issues may overweight the benefits of reduced build time.
Setting the Copy Local to false without considering deployment issues is not a good idea. 

Adding PostSharp to new projects, when it’s installed for some projects in solution.

Once PostSharp  is installed in  solution’s packages folder for some project(s), I often need to add PostSharp to another project in the same solutionSection “Adding PostSharp to your project using PostSharp HQ” of documentation described the process quite well.

[solution root ]packagesPostSharp.2.1.7.15toolsReleasePostSharp.HQ.exe.

Also you need to ensure that the project is checked out,i.e. not readOnly.

Helper method to Replace/Remove characters that do not match the Regular Expression

I have a few fields, that use regEx for validation. In case if provided field has unaccepted characters, I don’t want to reject the whole field, as most of validators do, but just remove invalid characters.
 I am expecting to keep only Character Classes for allowed characters and created a helper method to strip unaccepted characters.
 
The allowed pattern should be in Regex format, expect them wrapped in square brackets. function will insert a tilde after opening squere bracket , according to http://stackoverflow.com/questions/4460290/replace-chars-if-not-match.
 
[^ ] at the start of a character class negates it – it matches characters not in the class.
I anticipate that it could work not for all RegEx describing valid characters sets,but it works for relatively simple sets, that we are using.
 

        /// <summary>
               /// Replaces  not expected characters.
               /// </summary>
               /// <param name=”text”> The text.</param>
               /// <param name=”allowedPattern”> The allowed pattern in Regex format, expect them wrapped in brackets</param>
               /// <param name=”replacement”> The replacement.</param>
               /// <returns></returns>
               /// //        http://stackoverflow.com/questions/4460290/replace-chars-if-not-match.
               //[^ ] at the start of a character class negates it – it matches characters not in the class.
               //Replace/Remove characters that do not match the Regular Expression
               static public string ReplaceNotExpectedCharacters( this string text, string allowedPattern,string replacement )
              {
                     allowedPattern = allowedPattern.StripBrackets( “[“, “]” );
                      //[^ ] at the start of a character class negates it – it matches characters not in the class.
                      var result = Regex .Replace(text, @”[^” + allowedPattern + “]”, replacement);
                      return result;
              }

static public string RemoveNonAlphanumericCharacters( this string text)
              {
                      var result = text.ReplaceNotExpectedCharacters(NonAlphaNumericCharacters, “” );
                      return result;
              }
        public const string NonAlphaNumericCharacters = “[a-zA-Z0-9]”;

There are a couple of functions from my StringHelper class  http://geekswithblogs.net/mnf/archive/2006/07/13/84942.aspx ,
 that are used here.
    //            
               /// <summary>
               /// ‘StripBrackets checks that starts from sStart and ends with sEnd (case sensitive).
               ///           ‘If yes, than removes sStart and sEnd.
               ///           ‘Otherwise returns full string unchanges
               ///           ‘See also MidBetween
               /// </summary>
               /// <param name=”str”></param>
               /// <param name=”sStart”></param>
               /// <param name=”sEnd”></param>
               /// <returns></returns>
               public static string StripBrackets( this string str, string sStart, string sEnd)
              {
                      if (CheckBrackets(str, sStart, sEnd))
                     {
                           str = str.Substring(sStart.Length, (str.Length – sStart.Length) – sEnd.Length);
                     }
                      return str;
              }
               public static bool CheckBrackets( string str, string sStart, string sEnd)
              {
                      bool flag1 = (str != null ) && (str.StartsWith(sStart) && str.EndsWith(sEnd));
                      return flag1;
              }

               public static string WrapBrackets( string str, string sStartBracket, string sEndBracket)
              {
                      StringBuilder builder1 = new StringBuilder(sStartBracket);
                     builder1.Append(str);
                     builder1.Append(sEndBracket);
                      return builder1.ToString();
              }v

PostSharp deployment to build machine- use Setup installation, not NuGet package.

PostSharp has well documented different methods of installation. I’ve chosen installing NuGet packages, because according to 
NuGet is the easiest way to add PostSharp to a project without installing the product on every machine.
However it didn’t work well for me. I’ve added PostSharp NuGet package to one project in the solution.
 When I wanted to use PostSharp in other project, Visual Studio tab showed that PostSharp is not enabled for this project
I’ve added the NuGet package to the new project, which installed a new version of the package in the new Packages subfolder.
When I wanted to refer PostSharp from the third project, I’ve ended up with another version of PostSharp installed.
Additionally multiple versions of Diagnostics were created. It definitely causes confusion and errors.
 
More problems we experienced on build server. According to Using PostSharp on a Build Server
“If you chose to deploy PostSharp in the source repository, it does not need to be installed specifically on the build server. “
It didn’t work on our build server.
I kept getting errors “The “AddIns” parameter is not supported by the “PostSharp21″ task.” and “The “DisableSystemBindingPolicies” parameter is not supported by the “PostSharp21″ task.”
 

From my experience the only way to have the latest version of PostSharp working on the build server is to install it using Setup as described in Deploying PostSharp with the Setup Program
 
 
Gael acknowledged the issues with possible version conflicts. see http://support.sharpcrafters.com/discussions/problems/388-the-postsharp21-task-failed-unexpectedly
 
 

Convert collections of enums to collection of strings and vice versa

Recently I needed to convert collections of  strings, that represent enum names, to collection of enums, and opposite,  to convert collections of   enums  to collection of  
strings. I didn’t find standard LINQ extensions.
However, in our big collection of helper extensions I found what I needed – just with different names:
/// <summary>
/// Safe conversion, ignore any unexpected strings

/// Consider to name as Convert extension
/// </summary>
/// <typeparam name=”EnumType”></typeparam>
/// <param name=”stringsList”></param>
/// <returns></returns>
public static
List<EnumType> StringsListAsEnumList<EnumType>(this List<string> stringsList) where EnumType : struct, IComparable, IConvertible, IFormattable
    {
List<EnumType> enumsList = new List<EnumType>();
foreach (string sProvider in stringsList)
    {
    EnumType provider;
    if (
EnumHelper.TryParse<EnumType>(sProvider, out provider))
    {
    enumsList.Add(provider);
    }
    }
    return enumsList;
    }


/// <summary>
/// Convert each element of collection to string
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”objects”></param>
/// <returns></returns>
public static
IEnumerable<string> ToStrings<T>(this IEnumerable<T> objects)
{//from http://www.c-sharpcorner.com/Blogs/997/using-linq-to-convert-an-array-from-one-type-to-another.aspx
return objects.Select(en => en.ToString());
}

C# tip: do not use “is” type, if you will need cast “as” later

 

We have a debate with one of my collegues, is it agood style to check, if the object of particular style, and then cast  as this  type. The perfect answer of Jon Skeet   and answers in Cast then check or check then cast? confirmed my point.

//good
    var coke = cola as CocaCola;
    if (coke != null)
    {
        // some unique coca-cola only code
    }
    //worse
    if (cola is CocaCola)
    {
        var coke =  cola as CocaCola;
        // some unique coca-cola only code here.
    }

Code review recommendations and Code Smells

Some time ago Twitter told that I am similar to Boris Lipschitz . Indeed he is also .Net programmer from Russia living in Australia.
I‘ve read his list of Code Review points and found them quite comprehensive. A few points  were not clear for me, and it forced me for a further reading.

In particular the statement “Exception should not be used to return a status or an error code.” wasn’t fully clear for me, because sometimes we store an exception as an object with all error details and I believe it’s a valid approach. However I agree that throwing exceptions should be avoided, if you expect to return error as a part of a normal flow.
Related link: http://codeutopia.net/blog/2010/03/11/should-a-failed-function-return-a-value-or-throw-an-exception/

Another point slightly puzzled me
If Thread.Sleep() is used, can it be replaced with something else, ei Timer, AutoResetEvent, etc” . I believe, that there are very rare cases, when anyone using Thread.Sleep in any production code. Usually it is used in mocks and prototypes.

I had to look further to clarify “Dependency injection is used instead of Service Location pattern”.
Even most of articles has some preferences to Dependency injection, there are also advantages to use Service Location. E.g see http://geekswithblogs.net/KyleBurns/archive/2012/04/27/dependency-injection-vs.-service-locator.aspx.
http://www.cookcomputing.com/blog/archives/000587.html  refers to Concluding Thoughts of Martin Fowler
The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application

The post had a link to excellent article Code Smells of Jeff Atwood, but the statement, that “code should not pass a review if it violates any of the  code smells” sound too strict for my environment.

In particular, I disagree with “Dead Code” recommendation “Ruthlessly delete code that isn’t being used. That’s why we have source control systems!”. If there is a chance that not used code will be required in a future, it is convenient to keep it as commented or #if/#endif blocks with appropriate explanation, why it could be required in the future. TFS is a good source control system, but context search in source code of current solution is much easier than finding something in the previous versions of the code.

 
Related links: