Code Pyre

All Code Dies and Burns in Time

Dependency Injection & Inversion of Control Presentation

| Comments

Wednesday, July 15, 2009 at 6:00 PM

This session will cover Dependency Injection (DI) and Inversion of Control (IoC) and their relationship to SOLID design principles, techniques, and side effects in statically typed languages. In addition, IoC containers, how they work, their usages, patterns, and role as building blocks for loosely coupled applications will be explored.

Running an Elevated Child Process

| Comments

If you ever need to run a child process in an elevated state, you can easily set the Verbs property on the ProcessStartInformation to “runas” and the child process will ask for permission when started. You need to watch out the the user denying access however as a Win32Exception will be thrown with its NativeErrorCode = 1223. Here is a simple example launching the admin command prompt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
internal class Program
{
    private const int UserCanceled = 1223;

    private static void Main( string[] args )
    {
        var psInfo = new ProcessStartInfo
                     {
                         FileName = Environment.GetEnvironmentVariable ("ComSpec"),
                         UseShellExecute = true,
                         Verb = ( Environment.OSVersion.Version.Major >= 6 ) ? "runas" : string.Empty
                     };

        try
        {
            Process process = Process.Start( psInfo );
            Console.WriteLine( "Process has Id: {0}", process.Id );
            Console.WriteLine( "Waiting for app to exit." );
            process.WaitForExit();
        }
        catch ( Win32Exception ex )
        {
            if ( ex.NativeErrorCode != UserCanceled )
            {
                throw;
            }
            // permission was denied.
            Console.WriteLine( "The operation was canceled by the user." );
        }

        Console.WriteLine( "App exited, press enter to exit." );
        Console.ReadLine();
    }
}

More on Delay Loading .Net Assemblies

| Comments

You can build off of the previous article and make dealing with the dual libraries much easier using an IoC container. Instead of building an interface that constantly has to check which code path to execute based on the current platform, you can load the services into an IoC container. Once you know what platform you are on, you can reference the type forcing its assembly to be loaded into your current AppDomain (as shown previously). Once done, you can get the assembly through a few different ways and build up services with an IoC container.

You can use the assembly scanner in StructureMap, or other mechanisms in another container, to go through the assembly and build up services that you can run. If your platform specific assemblies reference a third contract definition assembly then you are in great shape. If not, you might use string resolution (container.Get(“MyService”)) to obtain the object and either duck type or reflection invoke its members.

Delay Loading .Net Assemblies

| Comments

I had to figure out how to make an application run as its native type while loading only the proper dlls for that platform – when the application runs on x64, load only x64 assemblies so that the application will run fully as x64 and the same for x86. The answer is counterintuitive and not straightforward.

Below is an example application that exhibits this behavior. The Amd64Library.Foo is defined in an assembly compiled for x64; the Win32Library.Foo is similarly defined in an x86 assemly. The Loader application is compiled as ‘Any CPU’ so it will load natively on either platform as long as we load the correct dependency assemblies. Remember that the using statement, is just a compiler hint and doesn’t effect the created MSIL application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#region Using Directives

using System;
using Win32Library;

#endregion

namespace LoaderApplication
{
    internal class Program
    {
        private static void Main( string[] args )
        {
            //RunLoadingBothAssemblies(); // will crash.
            RunLoadingOneAssembly();
            Console.ReadLine();
        }

        private static void RunLoadingBothAssemblies()
        {
            if ( IntPtr.Size == 4 )
            {
                var foo = new Foo();
                foo.Bar();
            }
            else
            {
                var foo = new Amd64Library.Foo();
                foo.Bar();
            }
        }

        private static void RunLoadingOneAssembly()
        {
            if ( IntPtr.Size == 4 )
            {
                LoadWin32Foo();
            }
            else
            {
                LoadAmd64Foo();
            }
        }

        private static void LoadAmd64Foo()
        {
            var foo = new Amd64Library.Foo();
            foo.Bar();
        }

        private static void LoadWin32Foo()
        {
            var foo = new Foo();
            foo.Bar();
        }
    }
}

The LoaderApplication references both x64 and x86 assemblies – yes, at the same time. The key is that the assemblies aren’t loaded into the process until the last possible moment. If you look at the RunLoadingBothAssemblies method, the moment you enter the method, the .NET runtime will load the assemblies for the types in that method. This means it will try to load the x64 library into a 32bit process and vise versa resulting in errors. The RunLoadingOneAssembly determines which platform is being used and then makes another call so that only the library needed is loaded.

There is a caveat to this method. The assemblies need to use separate namespaces or different type names. If both assemblies use the same namespace, you will run into type resolution issues as the compiler won’t know which class you are trying to load while referencing both assemblies. If you have source access to the assembly that has to be compiled for each platform, #if statements will allow you to easily adjust the namespaces or type names.

You can watch this application run on x64 and the process name will not have *32 as it will be running natively. So, if you want to have a single build of your application, but run on x64 and x86, this is one way to go.

Ruby First Impressions

| Comments

I decided to try out Ruby today. I have wanted to try it out for quite a while. Some of my impressions may be inaccurate, but I have done what I can. I have Zero interest in DB and web ‘programming’ so I am going to skip rails and related material.

What I like

  • very straightforward language
  • I loved that when I wanted to shift the elements of an array I found it was built-in
  • Class library
  • Being able to have a line of code like this; I wish I knew what to call it
    • return SolveUsingClosedFormExpression( n ) if ( 0..1474 ).include? n
    • return SolveUsingClosedFormExpression( n ) if (0..1474) === n
  • I will complain about this as well, but in writing the closed form Fibonacci solution, the data type changes allowing for huge results
1
2
3
4
5
def SolveUsingClosedFormExpression(n)
left = GOLDENRATIO ** n
right = (-GOLDENRATIOINV) ** n
  return ( (left  right) / ROOT5 ).to_i
end

What I didn’t like

  • Trying to figure out how to use gems (packages, not the tool) and files in the class library
  • Lack of type information
    • Yes, yes, I know, I know, but for a c, c++/cli, c# programmer, it feels just wrong
    • Declaring a variable feels like I am introducing a magic variable – poof it exists. At least in TI-Basic I had to declare my dynamically typed variables.
    • Lack of method return types
  • At least four ways to return a value from a method, see below.
  • Inconsistent API
    • was very frustrated when trying to use .power! only to find that it isn’t defined for Float types – I have to use ** everywhere.
  • Ruby is supposed to be super OO, but what object contains puts/print?

What I really didn’t like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def multiplyWithReturn(val1, val2 )
    result = val1 * val2
    return result
end

def multiplyLocalVariable(val1, val2 )
    result = val1 * val2
end

def multiplyNoVariables(val1, val2 )
    val1 * val2
end

def multiplyAssignToMethodName(val1, val2 )
    multiplyAssignToMethodName = val1 * val2
end

puts multiplyWithReturn(5,6)
puts multiplyLocalVariable(5,6)
puts multiplyNoVariables(5,6)
puts multiplyAssignToMethodName(5,6)

Running this code prints 30303030

I don’t know if I am missing a key ‘feature’ of the language, but at least four ways to return a value from a method just really irks me. Given that there is no return type of a method, reading code to determine what is returning a value and what methods are void seems ridiculous.

I have never programmed in a dynamic language, so it has been a bit of a ride. There a so many nuances to the language, it will take a while to get them down, but they allow for very concise code.

Continuous Build Systems

| Comments

I have gone through so many tools trying to create the right build environment that it is a bit disheartening. I have set up multiple continuous integration systems and it keeps getting easier, but there is still a bit too much friction.

I tried to look into using Team Foundation Server and Team Build, but the cost is very high for a startup (even with the top msdn subscription). This is compounded when you have external developers that must also hook into the system.

I have fallen for TeamCity but with one deal breaker for me: no FinalBuilder support. I submitted some feedback and I received a detailed response from JetBrains; I have always received great customer support from JetBrains:

There are several ways to support FinalBuilder:
1. You may start using CommandLine runner to start the process.
2. To Add custom FinalBuilder reporting you may use TeamCity service messages.
Please refer to
http://www.jetbrains.net/confluence/display/TCD4/Build+Script+Interaction+with+TeamCity
documentation article on service messages for details
3. You may start FinalBuilder from any other build scripts,
for example NAnt, MSBuild, Ant, Maven.
If you need custom logging, you may consider using TeamCity
Service messages as well
4. Write a build runner plugin for TeamCity. There are two
public available examples on the build runners at:
http://www.jetbrains.net/confluence/display/TW/Rake+Runner
and
http://svn.jetbrains.org/teamcity/plugins/fxcop/
Please feel free asking any questions on the integration.
5. Post an issue to our tracker at
http://www.jetbrains.net/tracker

I checked out the code for the build runner plugins, but it is too much work. It is hard not to sound lazy in saying that, but I haven’t used java since my sophomore year in college, and it doesn’t sit high on my list to spend hours getting a build runner going (I am looking for less friction, not more). I chose the 5th option and submitted a feature request TW-6442. With FinalBuilder support I don’t need any other build runners/tools as FinalBuilder most likely wraps them up in its UI.

One other feature that I would like to have, but am hesitant to request right now, is to be able to selected a successful build, and run a publish script (through the web interface (see Cruise)) that can tag the build and use the build artifacts to deploy that build to Dev/Stage/Production environment.

Ninject MessageBroker Update

| Comments

It has been a long time (10 months) since I worked with the Ninject MessageBroker and a couple things have changed since my last post. In the old version you had to connect the MessageBroker as a kernel component by hand. Since then the extension environment has been flushed out a lot more. Now you can register the MessageBrokerModule when constructing your kernel object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Diagnostics;
using System.Net;
using System.Text.RegularExpressions;
using Ninject;
using Ninject.Extensions.MessageBroker;

namespace NinjectMessageBroker
{
    internal class Program
    {
        private static void Main()
        {
            // Intialize our injection kernel adding message broker functionality.
            using (var kernel = new StandardKernel(new MessageBrokerModule()))
            {
                // Get the event publisher. It reads the current time and fires an event
                var pub = kernel.Get<TimeReader>();
                Debug.Assert(pub != null);

                // Get the subscriber, it waits to get the current time and writes it to stdout
                var sub = kernel.Get<TimeWriter>();
                Debug.Assert(sub != null);

                // Verify that they were wired together
                Debug.Assert(pub.HasListeners);
                Debug.Assert(sub.LastMessage == null);

                // Get the current time. It should automatically let the TimeWriter know
                // without either of them ever knowing of one another.
                pub.GetCurrentTime();

                // Wait to exit.
                Console.ReadLine();
            }
        }
    }

    internal class TimeWriter
    {
        public string LastMessage { get; set; }
 
        [Subscribe("message://Time/MessageReceived")]
        public void OnMessageReceived(object sender, EventArgs<string> args)
        {
            LastMessage = args.EventData;
            Console.WriteLine(LastMessage);
        }
    }

    internal class TimeReader
    {
        public bool HasListeners
        {
            get { return (MessageReceived != null); }
        }
 
        [Publish("message://Time/MessageReceived")]
        public event EventHandler<EventArgs<string>> MessageReceived;

        /// <summary>
        /// Gets the current time and updates all subscribers.
        /// </summary>
        public virtual void GetCurrentTime()
        {
            string text = GetWebPage();
            var regex = new Regex(@"dd:dd:dd");
            MatchCollection matches = regex.Matches(text);
            string time = ((matches.Count == 2) ? matches[1] : matches[0]).Value;
            SendMessage(time);
        }

        /// <summary>
        /// Gets the contents of a web page as a string.
        /// </summary>
        /// <returns></returns>
        private static string GetWebPage()
        {
            const string url = "http://www.time.gov/timezone.cgi?Eastern/d/-5";
            var webClient = new WebClient();
            return webClient.DownloadString(url);
        }

        /// <summary>
        /// Sends the message to all subscribers in a threadsafe manner.
        /// </summary>
        /// <param name="message">The message.</param>
        public void SendMessage(string message)
        {
            EventHandler<EventArgs<string>> messageReceived = MessageReceived;

            if (messageReceived != null)
            {
                messageReceived(this, new EventArgs<string>(message));
            }
        }
    }

    public class EventArgs<TData> : EventArgs
    {
        public new static readonly EventArgs<TData> Empty;

        static EventArgs()
        {
            Empty = new EventArgs<TData>();
        }

        private EventArgs()
        {
        }

        public EventArgs(TData eventData)
        {
            EventData = eventData;
        }

        public TData EventData { get; private set; }
    }
}

C++ if Statement Oddity

| Comments

I found that you can do work such as assigning a variable and executing a method outside of the main expression of an if statement. For example:

1
2
3
if( hRes = GetApplicationState(), NT_SUCCESS(hRes) ) {
    // Do something
}

Open Source Projects

| Comments

I had two open source projects: Ensurance, and IMAPI.Net.

  • Ensurance did not really fit into any particular group. It was a tool for me while Spec# was still a research project at MS. I wanted to be able to use pre/post conditions, parameter constraints, and tie them into logging and debugging. I don’t think that Spec# will do the last bit, but I am really looking forward to its release.
  • IMAPI.Net is a C# cd authoring library that wraps the IMAPI system in windows to allow programmers of any application to write to CD. It supports data and audio discs. It was expensive to test the library and the COM issues were a huge problem for a while.
    • PInvoke.net was a good help for the most part, but the marshalling took a long time to get right. I started the project back in .net 1.1 while working on my BS – and it worked. With each .NET release the project would have been easier to write with the COM interop support increasing. I used to be the lead of the XPBurn component project on GotDotNet before it shut down; in truth though, I had stopped supporting it a couple months before that. No one would read directions, read the forum, follow any kind of guidelines and would essentially expect me to figure out why they are using the code wrong. It became too much hassle in the end for what I got out of the project. It was a great learning experience though. Both projects are essentially dead and I will be closing down the Ensurance project on CodePlex and hosting the code for reference on GitHub. I will leave IMAPI.Net up on google code GitHub in case anyone ever finds use for the code. If I get the time I will try to add my PInvoke code to the wiki so others don’t have to work as hard as I did.

Yet Another Video Update (YAVU)

| Comments

Here is the latest PLAYXPERT video demo. While playing the game the user:

  • Starts playing a song.
  • Searches the web for a video.
  • Web browser
  • FLASH
  • Opens the Friends widget and initiates an IM session
  • Continues playing the game the whole time.

STAY IN GAME!