Archive for the ‘.NET’ category

Counting objects with Unity

April 30th, 2010

I’m using Unity for the first time on my current project (a WCF service), and the project is now fairly large with a significant amount of container configuration.  I’m taking advantage of lifetime managers to optimise object reuse, with PerThreadLifetimeManager being particularly attractive in a service – less garbage through object reuse but no locking to worry about.

I decided that it might be nice to see counts of the number of objects that Unity is creating for each type, to confirm that my lifetime configuration is optimal.  It turned out to be straightforward to do this with a Unity extension.

Here’s how the extension is used.  First, the extension is added to the container:

    var objectCounterExtension = new ObjectCounterExtension();
    container.AddExtension(objectCounterExtension);

 

At application shutdown a list of types and their associated instance counts can be output like this:

    IDictionary<Type,int> objectCounts = objectCounterExtension.ObjectCounts;

    foreach (var objectCount in objectCounts.OrderBy(oc => oc.Value))
    {
        Type type = objectCount.Key;
        int count = objectCount.Value;
        Console.WriteLine("{0}: {1}", type, count);
    }

 

The extension is quite simple, once you know how:

    class ObjectCounterExtension : UnityContainerExtension
    {
        ObjectCounterStrategy objectCounterStrategy;

        protected override void Initialize()
        {
            objectCounterStrategy = new ObjectCounterStrategy();
            Context.Strategies.Add(objectCounterStrategy, UnityBuildStage.Creation);
        }

        public IDictionary<Type, int> ObjectCounts
        {
            get { return objectCounterStrategy.ObjectCounts; }
        }
    }

    class ObjectCounterStrategy : IBuilderStrategy
    {
        Dictionary<Type, int> objectCounts = new Dictionary<Type,int>();

        public void PostBuildUp(IBuilderContext context)
        {
            IBuildKey buildKey = context.BuildKey as IBuildKey;
            if (buildKey == null)
                return;

            Type type = buildKey.Type;

            lock (objectCounts)
            {
                int count;
                if (objectCounts.TryGetValue(type, out count))
                {
                    objectCounts[type] = count + 1;
                }
                else
                {
                    objectCounts[type] = 1;
                }
            }
        }

        public Dictionary<Type, int> ObjectCounts
        {
            get
            {
                lock (objectCounts)
                {
                    return new Dictionary<Type, int>(objectCounts);
                }
            }
        }

        public void PostTearDown(IBuilderContext context) {}
        public void PreBuildUp(IBuilderContext context) {}
        public void PreTearDown(IBuilderContext context) {}
    }
 

32-bit client can’t connect to 64-bit COM server

March 10th, 2010

In a previous post I described how to host a COM server in a managed process using RegistrationServices.RegisterTypeForComClients.  I’ve been using this approach successfully for a while, but today I hit a snag.   I changed my C# server process from 32-bit to 64-bit, and immediately my 32-bit C++ client could no longer connect.

In theory it shouldn’t matter to the client whether the server is 32-bit or 64-bit – everything is out-of-process so there is no compatibility issue.   But I could see that COM was refusing to allow my client to connect to the running 64-bit server process, and instead was trying to launch a new server process (which was failing because I don’t allow that).

I have seen this type of problem many times before with COM, and it’s almost always due to security configuration – specifically the ‘run as’ configuration of the server.   So I spent a lot of time investigating that, but it turned out to be something much simpler.  Since Windows 2003 SP1, COM has a rule on x64 that if a 32-bit client CoCreates an out-of-proc server, COM will try to connect to a 32-bit server.  If the client is 64-bit, COM will try to connect to a 64-bit server.  So in my case, COM could see that the 64-bit server was running, but because the client was 32-bit it decided to launch a new (hopefully 32-bit) server process to service the request.

Fortunately there are two easy ways around the problem.  The first option is to modify the client to specify  CLSCTX_ACTIVATE_64_BIT_SERVER in the CoCreateInstance call.  The other (probably better) option is to add a PreferredServerBitness flag to the AppID registry entry for the server.

CLSCTX_ACTIVATE_64_BIT_SERVER is described here, and PreferredServerBitness here.

Using ANTLR to parse boolean queries

December 23rd, 2009

ANTLR is a well-known parser generator.  You supply it with a grammar and it builds a lexer and parser in the programming language of your choice.   I’ve just spent a few hours getting to grips with ANTLR basics, so I thought I’d document it for future reference.

My basic requirement is to transform an end-user boolean query to an XML document.   A simple example of a query I need to parse is:

john AND (joe OR sue)

I want the generated parser to produce the following syntax tree for this query:

AND
      john
      OR
            joe
            sue

It should then be trivial to walk the tree and write the XML document I need.

An ANTLR grammar is specified in a text file with a .g extension.   Here’s how my SimpleBoolean.g starts:

grammar SimpleBoolean;

options
{
  language = CSharp2;
  output = AST;
}

I’m specifying that the generated code should be C#, and that the parser should build an abstract syntax tree (AST).

Next I specify the lexer rules:

LPAREN : '(' ;
RPAREN : ')' ;
AND : 'AND';
OR : 'OR';
WS :  ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}  ;
WORD :  (~( ' ' | '\t' | '\r' | '\n' | '(' | ')' ))*;

These rules are used to turn the source text into a stream of tokens.  So parentheses and operators are special tokens, and anything else is either whitespace (which is skipped) or a word.

Finally I specify the parser rules:

expr : andexpr;
andexpr : orexpr (AND^ orexpr)*;
orexpr : atom (OR^ atom)*;
atom : WORD | LPAREN! expr RPAREN!;

This is the confusing bit.  The chain of expressions (expr –> andexpr –> orexpr) is used to signify precedence.  In this case I’ve made OR higher precedence than AND.   Also notice that andexpr (for example) does not require an AND – it is optional.  This is why the grammar supports an expr containing only an OR, even though expr is defined in terms of andexpr.

The symbol suffixes (^ on the operators and ! on the parentheses) are there to direct the AST generation.  ^ signifies a tree branch, whereas ! indicates something that should be omitted from the tree.   Anything else is a leaf.   (The parentheses are omitted because they are redundant – the structure of the tree gives the order of evaluation implicitly.)

So SimpleBoolean.g is now complete, and all that remains is to ask ANTLR to generate a C# parser from it.  I used the ANTLRWorks IDE for this, but you could use the command-line.   Once the C# files are generated, and the ANTLR .NET runtimes files added to a C# project, we’re ready to write some C#.   Here’s some code that parses a query and then walks the syntax tree and writes the nodes to the console:

class Program
{
    static void Main(string[] args)
    {
        ANTLRStringStream expression = new ANTLRStringStream("john AND (joe OR sue)");
        var tokens = new CommonTokenStream(new SimpleBooleanLexer(expression));
        var parser = new SimpleBooleanParser(tokens);

        SimpleBooleanParser.expr_return ret = parser.expr();
        CommonTree ast = (CommonTree)ret.Tree;
        Print(ast,0);
    }

    static void Print(CommonTree tree, int level)
    {
        Console.WriteLine(new string('\t', level) + tree.Text);
        if (tree.Children != null)
            foreach (CommonTree child in tree.Children)
                Print(child,level+1);
    }
}

which prints the following:

AND
        john
        OR
                joe
                sue

For a more comprehensive ANTLR tutorial, see this series of blog posts.