.Net Gotcha – Private Classes With Access To Containing Classes’s Protected Variables (Or Not)

A friend and I were working on some code together when we found an interesting edge case in .Net that neither of us knew about.

This is what we knew: if you have a class with a protected field in it, if you declare a private class inside of that class, the private class can access the protected variable. The example below shows what this looks like.

  public class ParentClassWithProtectedField
    {
        protected readonly int protectedField;

        private class PrivateClassInParentClass
        {
            public void Method(ParentClassWithProtectedField parent)
            {
                Console.WriteLine(parent.protectedField); //Me Work Good!
            }
        }
    }

And this is what we learned: If you create a child class that inherits from the parent class, and declare another Private class in the child class, you cannot access the parent’s protected field from the private class in the child class. I know that was a ton of Parent/Child/Private classes in a short sentence, so here’s an example, building on the previous one, of what won’t work in .NET.

    public class ChildClassOfParentClass : ParentClassWithProtectedField
    {
        private class PrivateClassInChildClass
        {
            public void Method(ParentClassWithProtectedField parent)
            {
                Console.WriteLine(parent.protectedField); // NO WORK!
            }
        }
    }
Advertisements

.Net SQL Parsing – Using the TSqlParser library

As a bit of a preface to this post: it is hard to find a free SQL Parser for .NET.

There is a company that has a terrible library that they charge $150 bucks for. There are a couple of incomplete implementations done for school projects or for narrowly focused tasks.

So if you want a no-strings attached free parser for SQL, you’re out of luck.

However, since most people who want a .NET parser are writing code on a Windows machine, and use Visual Studio, there is (lightly documented) hope: the TSqlParser library that ships with Visual Studio.

This is a fully featured parsing library for SQL Server SQL syntax. I’m not sure about the support of other DB’s SQL syntax, but I would imagine it’s poor.

On an x64 Windows machine, using Visual Studio 2010, the dll’s which contain the TSqlParser library are located at:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VSTSDB

The class TSql100Parser in Microsoft.Data.Schema.ScriptDom.Sql gets you the parser for Sql Server 2008.

To instantiate an instance of the TSql100Parser class, you have to supply the constructor with one parameter:

public TSql100Parser(bool initialQuotedIdentifiers )

The docs for this are better than trying to figure out what initialQuotedIdentifiers means:

Specifies whether quoted identifier handling is on.

I’m guessing this has to do with declaring aliases for columns like this:

select 
   bar as 'This is the alias for foo.bar'
from 
   tblFoo
--instead of like this:
select
    bar as [This is the alias for foo.bar]
from
    tblFoo

Using the parser is relatively simple. Once you reference the correct dll’s in your project:

var parser = new TSql100Parser(true); 
var script = parser.Parse(reader, out errors) as TSqlScript;

foreach (TSqlBatch batch in script.Batches)
{
    foreach (TSqlStatement statement in batch.Statements)
    {
        //At this point, you have a collection of SQL Statements... 
        //that can contain collections of SQL Statements...  
    }
}

My comment in the code above is to help you understand something about parsing SQL – almost every relationship is expressed as a tree, where something contains more of the same thing, and that thing may contain more of the same thing, or maybe not.

Which means the easiest way to navigate the data is recursively. In other words, the Rules for using TSqlParser:

  1. LEARN TO LOVE THE RECURSION.
  2. Refer to the Rules for using TSqlParser

I’ll give you an example scenario to show you what you’re up against.

One common scenario is searching your code for SELECT statements. Select statements can be contained in:

  • Stored Procedures
  • If Statements
  • While Statements
  • BEGIN statements
  • Try/Catch Blocks

I’m sure I’m missing some cases.

So it’s not as simple as saying “give me all the statements that are select statements”. Instead, you have to write something like:

function ProcessStatements(statements)

    foreach(statement in statements) 
        if statement is a Stored Procedure
           ProcessStatements(statement.MyStatements)
        if statement is an If Statement
           ProcessStatements(statement.MyStatements)
        if statement is a While Statement
           ProcessStatements(statement.MyStatements)
        if statement is a Select Statement
           ProcessSelect( statement)

So once you get your select statement (or your collection of select statements), how do you process them?

Well unfortunately it’s not straightforward. The SelectStatement class contains a field called QueryExpression – this field contains what kind of Select we’re dealing with.
As far as I can determine, there are three types of QueryExpressions:

  • QuerySpecification
  • This is an actual SELECT statement

  • BinaryQueryExpression
  • This is a UNION or similar expression between two SELECT statements

  • QueryParenthesis
  • This is a SELECT surrounded by parenthesis. In other words, a sub-select

So again, if you only want SELECT statements, you have to weed through the three types of QueryExpressions until you get to the underlying SELECT statements.

So eventually you’ll get to a list of QuerySpecifications (which represent the SELECT statements from your original query).

Now here comes the good stuff: you can now weed through the SELECT fields programmatically and get out whatever information you want. Here are some of the fields on QuerySpecification:

FromClauses     Gets a list of FROM clauses.
GroupByClause   Gets or sets a GROUP BY clause.
HavingClause    Gets or sets a HAVING clause.
Into            Gets or sets the into table name.
SelectElements  Gets a list of the selected columns or set variables.
TopRowFilter    Gets or sets the usage of the top row filter.
UniqueRowFilter Gets or sets the unique row filter value.
WhereClause     Gets or sets a WHERE clause.

Just tons of SELECT goodness. However, be warned: each of these fields contains lists with multiple subclasses. So more recursive diving if you want to get something very specific out of this select data.

To get farther you might have to dive into the docs.
Link to MSDN Namespace Docs

Free Collection of Microsoft E-Books

If you’re a Microsoft Dev, want to learn a bit more about the following products:

  • SharePoint 2010
  • Sql Server 2012
  • Visual Studio 2010
  • Windows 8
  • Windows Phone 7
  • Office 365
  • Office 2010
  • ASP.NET 4.5 Web Forms
  • ASP.NET MVC 4
  • Microsoft Dynamics CRM 2011 (God Rest Your Soul)

Microsoft has released a bunch of free e-books about these technologies (and a few others).

The links to the e-books:

Microsoft Free E-Books – Page 1
Microsoft Free E-Books – Page 2

Using StructureMap to collect and use all instances of a given type

Had an issue at work where I wanted to store all of my rules and various handlers for a class outside of the class definition, so I could better test the component.

Found an easy way to add all your rules into StructureMap, and then retrieve those rules as a list via constructor injection.

using System.Collections.Generic;
using System.Linq;
using System.Text; 
using StructureMap;
using StructureMap.Configuration.DSL;

public class TravelRegistry : Registry
{ 
	public TravelRegistry()
	{  
		For<ITransportHandler>().Add<ApprovedAccommodationHandler>();
		For<ITransportHandler>().Add<ApprovedCharterFlightHandler>();
		For<ITransportHandler>().Add<ApprovedCommercialFlightHandler>();
		For<ITransportHandler>().Add<ApprovedGroundTransportHandler>();

		For<IEnumerable<ITransportHandler>>().Use(x => x.GetAllInstances<ITransportHandler>());

		For<ITravelRule>().Add<StartLessThanEndRule>();
		For<ITravelRule>().Add<CurrentEndsAfterPreviousRule>();
		For<ITravelRule>().Add<CurrentStartAfterPreviousEndRule>();
		For<ITravelRule>().Add<UniqueEndsRule>();
		For<ITravelRule>().Add<UniqueStartAndEndRule>();
		For<ITravelRule>().Add<UniqueStartsRule>();

		For<IEnumerable<ITravelRule>>().Use(x => x.GetAllInstances<ITravelRule>());

	} 
}

Posting an IEnumerable of Interfaces back from your Views by extending the DefaultModelBinder

Please note I came across a bug in the code, and revised this post on 31/07/2012.

Came across an interesting problem. In ASP.Net MVC, you can easily pass an enumerable of interfaces to your views from your controllers. As long as you have DisplayTemplates and EditorTemplates defined for the subclasses, then those classes will be rendered correctly from your enumerable of the parent interfaces.

However, if you then POST to a controller method that accepts an IEnumerable, you’ll get the error message:

Cannot create an instance of an Interface

In looking for a solution, I found some examples online that handled abstract classes. Unfortunately, none of those examples had a way to post data back without modifying the views, and I couldn’t figure out a way either.

So here is my solution:

1) Modify your EditorTemplates to use the Type extension method defined below. This will write a hidden field to the view that defines the class being used. Example:

@Html.Type(Model)

2) Register the SectionModelBinder below in Global.asax. Example:

ModelBinders.Binders.DefaultBinder = new SectionModelBinder();

3) That’s it! You should be on your way to POSTing a generic list of different subclasses to a controller method.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace ProofOfConcept
{
    public class SectionModelBinder : DefaultModelBinder
    {
        public const string ModelTypeNameKey = "ModelTypeName";

        ///
<summary>
        /// Creates the model.
        /// </summary>
        /// The controller context.
        /// The binding context.
        /// Type of the base.
        /// The instantiated model
        ///
        ///
        /// You must create a hidden field named 'ModelTypeName' on the View,
        /// where the value is the Full name of the class you are trying to create.
        /// The HtmlHelper extension method 'Type' was designed to create this field
        /// and hide the implementation details.
        ///

        /// Currently, the model you trying to create must inherit from a base class
        /// that is the same assembly.
        ///
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type baseType)
        {
            if (baseType.IsInterface &&
                (baseType != typeof(IEnumerable)) &&
                !baseType.GetInterfaces().Any(t => t == typeof(IEnumerable)) &&
                !(baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(IEnumerable)))
            {
                var modelTypeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName                                + "." + ModelTypeNameKey);

                if (modelTypeValue == null)
                    throw new Exception("View does not contain " + bindingContext.ModelName + "." + ModelTypeNameKey + " field.");

                var subclassName = modelTypeValue.AttemptedValue;

                if(string.IsNullOrWhiteSpace(subclassName ))
                    throw new Exception("View for " + bindingContext.ModelName + " does not have a value set for the " + ModelTypeNameKey + " field.");

                var subclassType = baseType.Assembly.GetTypes().SingleOrDefault(x => (x.FullName == subclassName));

                var model = CreateInstance(baseType, subclassType, subclassName);

                if (model != null)
                {
                    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, subclassType);
                }

                return model;
            }

            return base.CreateModel(controllerContext, bindingContext, baseType);
        }

        protected virtual object CreateInstance(Type baseType, Type subclassType, string subclassName)
        {
            if (subclassName == null)
                throw new ArgumentNullException("subclassName");

            if (subclassType == null)
                throw new Exception("Could not find model " + subclassName);

            if (!subclassType.GetInterfaces().Any(t => t == baseType))
                throw new Exception("The model of type " + subclassName + " does not implement " + baseType.FullName);

            return Activator.CreateInstance(subclassType);
        }
    }
}
namespace System.Web.Mvc.Html
{
    public static class HtmlHelperExtension
    {
        public static MvcHtmlString Type(this HtmlHelper htmlHelper, object value)
        {
            if (htmlHelper == null) throw new ArgumentNullException("htmlHelper");
            if (value == null) throw new ArgumentNullException("value");

            return htmlHelper.Hidden(SectionModelBinder.ModelTypeNameKey, value.GetType().FullName);
        }
    }
}

Setting up a .NET build server WITHOUT installing Visual Studio

I’ve been tasked with upgrading my client’s build server. It currently builds VS 2080 solutions in .NET 3.5 – and I’ve been pushing to upgrade everyone to Visual Studio (VS) 2010 and eventually .NET 4.0. I want to upgrade the server to build a VS 2010 solution in .NET 3.5. This will allow everyone to upgrade to VS 2010 while leaving the task of upgrading the production web servers to another day.

I try the easy approach. I install .NET 4.0 on the build server and run the MSBuild scripts that already exist.

Nothing good happens. I do a little digging and find out that you need to install the Windows SDK to get MSBuild to work.

So I get the Windows SDK – Microsoft Windows SDK for Windows 7 and .NET Framework 4 – and install it.

Nothing good happens. I dig a little further and find out that by default MSBuild installs pointing at the VS version of the Windows SDK whether it is there or not.

Also, the Windows SDK does not care about the settings of MSBuild, so when you install the SDK it doesn’t fix this or update this. Which I understand from the SDK team’s point of view, but it would have been a nice fix.

Registry View of the MSBuild Settings for .NET 4.0

Registry View of the MSBuild Settings for .NET 4.0

The important thing to note is the keys which have “7.0a” in their values. 7.0a is the version of the Windows SDK that ships with Visual Studio 2010. If you download the SDK from Microsoft you get version 7.1. So I go in and manually change all those 7.0a to 7.1.

It builds! But it fails. For some reason, I can’t get any of the XmlSerializers dll (which are needed by web projects that have web services or WCF) to generate correctly.

The normal dll’s compile into .NET 3.5 versions (which is what I want), but the XmlSerializers dlls all generate in .NET 4.0. What’s going on here?

Another bug. The Windows SDK installer, by default, installs the WRONG keys into the registry. This apparently only affects certain edge cases, like trying to generate XmlSerializer dll’s with MSBuild from .NET 4.0 into .NET 3.5. I’m guessing the Visual Studio installer fixes this when it runs.

The issue is documented here: Windows 7.1 SDK targeting .NET 3.5 generates wrong embedded Resources.

So, another trip to the registry. This time, to the Microsoft-SDKS section. There are two bugs here:
1) All the keys need to have a dash after the “WinSDK” portion
2) Some of the fields have an “-86” in their key, which needs to be “-x86”

A view of the registry for the Windows SDK

The final view of all the keys in the Microsoft-SDKS section of the registry.

One more try. Build successful. 🙂

Finished the Nike+ Importer for www.runningahead.com

I finally finished up the Nike+ data importer for http://www.runningahead.com.

The code for the importer can be checked out at my Github repository:

https://github.com/duereg/NikePlusImporter

I got a small test project up for this, which walks through everything but doesn’t Mock up the calls to the Nike+ service (I couldn’t be bothered).

Let me know what you think.