20130801

Firefox Feedly RSS option

If you use Firefox with a RSS button and want the default RSS page to offer a Feedly option here is what you need to do:
  • go to the about:config page
  • search "browser.content" without the quotes
  • replace one of the options you never use with feedly by
    • changing the title
    • changing the uri to
      • http://cloud.feedly.com/#subscription%2Ffeed%2F%s

It should look something like this:

Firefox Feedly Config

20130217

How you tell a good IT job from a bad one

Anybody in the IT industry eventually hears about the Joel Test.

I don't think that all of those things always apply to all IT jobs, but if you don't have most of them it is a pretty good sign there might be something wrong there.

There used to be an even better resource on a post on Stack Exchange that went about it from the other way, a list of red flags called the Anti Joel Test (don't bother to click, like a lot of things these days Stack Exchange mod farmers have removed it after over a year of upvotes).

You can find some of the original contents in the internet archive if you care to look.  The least difficult to read version seems to be the 2010 crawl.

Since I was using this like periodically in discussions and it is effectively dead, I thought it might be useful to preserve the main points here.  This is more or less in the order it was in the archived version skipping some of the responses that were effectively jokes:

  • Does the company insist on being very process heavy?
  • Do you do your development work on the live production server?
  • Do web filters block out forums making it difficult to research online?
  • Is the work environment noisy making it difficult to concentrate?
  • Is the work schedule an inflexible 8-5?
  • Do they expect tier 1 support in addition to your programming duties?
  • Does management have no true understanding of development?
  • Despite this, does management "think" they know development?
  • Do they fail to provide an outlet for being creative?
  • Do they fail to provide adequate development hard/software?
  • Do they deny developers admin rights to their own box?
  • Is there a dress code which includes a suit and tie? (or other customer facing dress code req's)
  • Is the chief technology officer an accountant?
  • Do developers have to account for their time in small increments?
  • Is refactoring discouraged?
  • Is the development team driven and controlled by sales people?
  • Do you usually promise to create the documentation after the software is finished?
  • Do you hire cheap people because they cost less?
  • Do you let inexperienced people create new products, but experienced people finish and maintain whatever is created?
  • Are strategic alliances (instead of technical merits) the main argument for resp. against the use of a technology?
  • Does your source control consist of physically backing up your source tree into a source.backup.n directory every time you want to make too many changes?
  • Does management think that paying a consultant to teach on-site classes is the most effective way for developers to learn a new technology?
  • Is there at least one case where a single person unilaterally makes software architecture decisions for more than three simultaneous, ongoing, non-trivial projects?
  • Is the coding standard an inviolable straitjacket that serves to hinder rather than inform?
  • Is StackOverflow blocked at work?
  • Would management view time off to speak at a conference or other technical gathering relevant to your work as suspicious and/or unconditionally refuse it?
  • Do developers feel frustrated or stymied by managerial/organizational problems more often than technical ones?
  • You're required to use IE6 at work. And you do web development.
  • Did the last developer you hired leave quickly? Usually high turnaround in IT means at least one of two things: A) The code is wretched and unmaintainable, and/or B) Management has highly unrealistic expectations about programmers.
  • Also: Does the team not care about learning new things, experimenting with new technologies and at the very least check out what's "new" in their programming world? If they are like this then it means the team is a bunch of incompetent Morts and are mediocre at best.
  • Is the primary development language an in-house only product?
  • Do I need to work weekends just before a big release?
  • Is access to the internet blocked at work?
  • Are they inflexible about letting you work from home occasionally?
  • Does the management do task effort estimation?
  • Was it too easy for you to get an offer from the company? (All you had to do during the interview was to explain quicksort)
  • Does the average developer have more than 3 hours of meetings a week?
  • Are working hours strictly enforced? Am I supposed to work 9-5 daily with no exceptions?
  • Do you only release a product if there aren't any more known bugs?
  • Is my manager non-technical?
  • Are there more than 3 people who can assign work to me without any approval?
  • Is the coding standard an inch thick?
  • no coffee or crappy coffee indicates a lot. It says to me that a company would rather do the bare minimum to pacify employees than to spend a bit more and make them happy
  • Do you expect developers to serve support requests while doing project work?( Do you let the urgent override the important?)(without accounting for the time lost to project work)
  • Are your developers unhappy?
  • Do they hire developers primarily based on academic degrees?
  • unpaid overtime a regular occurrence, and nothing is being done to change that
  • rules set in stone, even if the programmer have a good reason to break them
  • Do employees from multiple departments without an ownership stake in technology make suggestions about programming techniques or implementation details and expect to be taken seriously
  • management judges projects by their costs only and are unable to judge them by their value earned
  • Are developers regularly asked to complete numerous training courses prescribed by management to tick some bigger company-wide goal that is completely irrelevant to what developer is paid for
None of that list is really my ideas, but this is something I think about on and off since the unnecessary death spiral experience of one of my previous employers and enough time has passed I think I should be able to look at it a bit more objectively and learn something.

20120609

Generic Windows Service Host

Windows services are pretty useful, but debugging them from visual studio can be kind of a pain and repeating all the service and installer guts in every one gets a little old if you have to do very many of them.

Below is a console app that hosts a library as a service.  It can also run the service as a console app so you can F5 debug straight from studio and it has the ability to install and uninstall the service.

using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using thisproject.Host;
using System.Diagnostics;
 
namespace ConsoleServiceBase
{
 
    //this file is in the order it is to prevent you from using the designer.  do not reorder.  C# insits this is a designer file incorrectly, but it wasn't worth switching to VB to correct that
 
    /// 
    /// Static class that allows the executable to locate the library to run that is a descendant of ConsoleServiceLibrary
    /// 
    internal static class ServiceWorkLibraryFinder
    {
        private static Type LibraryType;
 
        internal static Type FindWork()
        {
            if (LibraryType == null)
            {
                foreach (FileInfo f in (new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)).GetFiles("*.dll"))
                {
                    var a = Assembly.LoadFrom(f.FullName);
                    LibraryType = a.GetTypes().FirstOrDefault(x => x.IsSubclassOf(typeof(ConsoleServiceLibrary)));
                    if (LibraryType != nullbreak;
                }
            }
            return LibraryType;
        }
    }
 
    //do not move this class to the top of the file - the designer is not to be used on this class
 
    /// 
    /// Service Installer class for the /install /uninstall command line options of the ServiceConsole
    /// 
    [RunInstaller(true)]
    public class CustomServiceInstaller : Installer
    {
        public CustomServiceInstaller()
        {
            var WorkType = ServiceWorkLibraryFinder.FindWork();
 
            ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
            ServiceInstaller serviceInstaller = new ServiceInstaller();
 
            //# Service Account Information
            serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
            serviceProcessInstaller.Username = null;
            serviceProcessInstaller.Password = null;
 
            //# Service Information
            serviceInstaller.DisplayName = WorkType.FullName;
            serviceInstaller.StartType = ServiceStartMode.Automatic;
            serviceInstaller.ServicesDependedOn = ((ConsoleServiceLibrary)Activator.CreateInstance(WorkType)).ServicesDependedOn;
            serviceInstaller.ServiceName = WorkType.FullName;
 
            this.Installers.Add(serviceProcessInstaller);
            this.Installers.Add(serviceInstaller);
        }
    }
 
 
    /// 
    /// ServiceConsole is a console app that can also run as a windows service.  It does no meaningful work on its own but will run the first library that is a descendant of ConsoleServiceLibrary in its filesystem path when run.
    /// 
    class ServiceConsole : ServiceBase
    {
        private static Type WorkType = ServiceWorkLibraryFinder.FindWork();
        private static ConsoleServiceLibrary WorkInstance;
 
        public ServiceConsole()
        {
            this.ServiceName = WorkType.FullName;
            this.AutoLog = true;
            WorkInstance = (ConsoleServiceLibrary)Activator.CreateInstance(WorkType);
        }
 
        protected override void OnStart(string[] args)
        {
            WorkInstance.NonBlockingStart();
            base.OnStart(args);
        }
 
        protected override void OnStop()
        {
            WorkInstance.BlockingStop();
            base.OnStop();
        }
 
        // The serviceinstaller is missing the bit to set recovery options, this does it through sc.exe.  It will always restart on fail after 60 seconds.
        static void SetRecoveryOptions(string serviceName)
        {
            int xCode;
            using (var process = new Process())
            {
                var startInfo = process.StartInfo;
                startInfo.FileName = "sc";
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
 
                // tell Windows that the service should restart if it fails
                startInfo.Arguments = string.Format("failure {0} reset= 0 actions= restart/60000", serviceName);
 
                process.Start();
                process.WaitForExit();
 
                xCode = process.ExitCode;
 
                process.Close();
            }
 
            if (xCode != 0)
                throw new InvalidOperationException();
        }
 
 
        static void Main(string[] args)
        {
            if (Environment.UserInteractive)
            {
                if (args.Contains("/install"))
                {
                    (new AssemblyInstaller(Assembly.GetExecutingAssembly(), new string[] { AppDomain.CurrentDomain.BaseDirectory })).Install(null);
                    SetRecoveryOptions(WorkType.FullName);
                    (new ServiceController(WorkType.FullName)).Start(new string[] { });
                }
                else if (args.Contains("/uninstall"))
                {
                    try
                    {
                        (new ServiceController(WorkType.FullName)).Stop();
                    }
                    catch (Exception)
                    {
                    }
 
                    (new AssemblyInstaller(Assembly.GetExecutingAssembly(), new string[] { AppDomain.CurrentDomain.BaseDirectory })).Uninstall(null);
                }
                else
                {
                    //be a debuggable console app
                    Console.WriteLine("add /install to the command line to install and run as a service");
                    Console.WriteLine("add /uninstall to the command line to stop the service and uninstall");
                    Console.WriteLine("");
                    var p = new ServiceConsole();
                    p.OnStart(null);
                    Console.WriteLine("running - press enter to kill...");
                    Console.ReadLine();
                    p.OnStop();
                }
            }
            else
            {
                //be the service
                ServiceBase.Run(new ServiceConsole());
            }
        }
    }
}

If you compile and run the executable it will detect that you are in userspace and run as a console app.  If you run it with the /install flag it will set itself up to run as a service.  The /uninstall removes the service.  The easiest way to set this up in studio is to make a console project then replace the main program class with the code above IMHO.

This by itself doesn't really do anything,but the first code references a class called ConsoleServiceLibrary which looks like this:


namespace thisproject.Host
{
    /// 
    /// Inherit this class to create a library that can be run by the ConsoleServiceHost
    /// 
    public abstract class ConsoleServiceLibrary
    {
        /// 
        /// override this method with something that starts the process and immediately returns control to the host
        /// 
        public abstract void NonBlockingStart();
 
        /// 
        /// override this method with something that signals the worker process to stop then does not return until stoppage is complete
        /// 
        public abstract void BlockingStop();
 
        /// 
        /// override this to return an array of services this service depends on.  Names must be ServiceNames not the friendly DisplayNames
        /// 
        public abstract string[] ServicesDependedOn { get; }
    }
}


This class also goes in the consoleproject.  Once you have built the console project you can set it as an external reference to separate projects (I usually use dll projects for the descendants) then inherit and implement the abstract class.  When the secondary project is built you just run the console executable that gets put in the bin directory and it will pick up and run the first dll that has a ConsoleServiceLibrary implementation in the same directory.  For the F5 goodness you need to set the dll project to start the console app out of bin\debug manually.

There are a couple limitations in this version that I do not mind, but you may:
  • there can only be one service dll in the folder with the host exe
  • the descendant dll doesn't end up being able to use a normal app.config easily because of the names and the path issues services bring.
  • the descendant type name will be the service name
  • the service always installs to run as system
This approach is something I needed  to be able to debug easily, deploy with simple scripts and file copy, hide the service weirdness from some of my coworkers who are really more asp devs than internals devs, and to make a big set of services quickly that all behave the exact same way from the servicehost side of things.  I mostly worked this out through trial and error and reading the msdn docs and code blogs over the years so there are probably better ways of doing some of these things.

20120425

simple js geolocation test

Nothing really special here, js Geolocation pulling a static google map image as a very simple example to test some browser settings.  See the code below or run the example here.

You Are Here:<br />
<img id='gmpsimg' />

<script type="text/javascript">
 if (navigator.geolocation) {
  var timeoutVal = 10 * 1000 * 1000;
  navigator.geolocation.getCurrentPosition(
    gmp, 
    showerror,
    { enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 }
  );
 }
 else {
  alert("Geolocation is not supported by this browser");
 }

 function gmp(position) {
  document.getElementById('gmpsimg').src = 
  'http://maps.googleapis.com/maps/api/staticmap?markers=color:blue%7Clabel:X%7C'
  + position.coords.latitude + ',' + position.coords.longitude +
  '&zoom=17&size=400x400&sensor=true&maptype=hybrid';
 }

 function showerror(error) {
  var errors = { 
    1: 'Permission denied',
    2: 'Position unavailable',
    3: 'Request timeout'
  };
  alert("Error: " + errors[error.code]);
 }
</script>

20110611

New Job

Monday I start at Excellence in Motivation. They make marketing and performance improvement programs.  They seem to be headed in a good direction and are much closer to home.  More than 50 miles closer, so I really couldn't turn that combo down now that my son is old enough to start asking where I am all the time.  There is also a pretty good chance at this place I can keep what most people would consider a normal schedule for the first time in my career.

Thanks to everyone that was sending leads, and if any of you are currently looking I have a few I didn't even get a chance to interview for I can pass along.

20110511

even better type conversion between similar objects

My last post showed how to use compiled linq expressions as delegates to make a type converter.  I noted that an MSIL solution would be faster.  I am not a MSIL expert by any means, but here is my best attempt as using DynamicMethod and MSIL to create a delegate converter.

It does the same thing as the linq version but requires separate assign blocks for each combination of field and property.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;

namespace typeoverridedemostrater
{

    static class SuperConverter<T1, T2> where T2 : new()
    {

        private static Dictionary<Tuple<System.Type, System.Type>, MethodInvoker> converters = new Dictionary<Tuple<System.Type, System.Type>, MethodInvoker>();
        delegate T2 MethodInvoker(T1 inpt);

        static public T2 Convert(T1 i)
        {
            var key = new Tuple<System.Type, System.Type>(typeof(T2), typeof(T1));
            if (!converters.ContainsKey(key))
            {
                DynamicMethod dm = new DynamicMethod("xmethod", typeof(T2), new Type[] { typeof(T1) }, typeof(T2));
                ILGenerator il = dm.GetILGenerator();
                il.DeclareLocal(typeof(T2));
                il.Emit(OpCodes.Newobj, typeof(T2).GetConstructor(System.Type.EmptyTypes));
                il.Emit(OpCodes.Stloc_0);

                (from z in typeof(T1).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 join y in typeof(T2).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_0);
                     il.Emit(OpCodes.Ldfld, typeof(T1).GetField(a));
                     il.Emit(OpCodes.Stfld, typeof(T2).GetField(a));
                 });

                (from z in typeof(T1).GetProperties().Select(a => new { name = a.Name, type = a.PropertyType })
                 join y in typeof(T2).GetProperties().Where(b => b.CanWrite).Select(a => new { name = a.Name, type = a.PropertyType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_0);
                     il.Emit(OpCodes.Callvirt, typeof(T1).GetProperty(a).GetGetMethod());
                     il.Emit(OpCodes.Callvirt, typeof(T2).GetProperty(a).GetSetMethod());
                 });


                (from z in typeof(T1).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 join y in typeof(T2).GetProperties().Where(b => b.CanWrite).Select(a => new { name = a.Name, type = a.PropertyType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_0);
                     il.Emit(OpCodes.Ldfld, typeof(T1).GetField(a));
                     il.Emit(OpCodes.Callvirt, typeof(T2).GetProperty(a).GetSetMethod());
                 });

                (from z in typeof(T1).GetProperties().Select(a => new { name = a.Name, type = a.PropertyType })
                 join y in typeof(T2).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_0);
                     il.Emit(OpCodes.Callvirt, typeof(T1).GetProperty(a).GetGetMethod());
                     il.Emit(OpCodes.Stfld, typeof(T2).GetField(a));
                 });

                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ret);

                var dg = (MethodInvoker)dm.CreateDelegate(typeof(MethodInvoker));

                converters.Add(key, dg);
            }

            return (T2)converters[key](i);
        }
    }
}

Compared to the Linq version at 100 million repetitions (at lower numbers the results are less predictable):

Linq: 94.579 seconds vs MSIL: 93.423 seconds


Some of that time is consumed dealing with the delegates, so you can transform that into a full dynamic assembly where you can have base classes and real instance references like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Threading;
using System.Reflection;


namespace typeoverridedemostrater
{

    static class SuperConverterII<T1, T2> where T2 : new()
    {

        private static Dictionary<Tuple<System.Type, System.Type>, convertbase<T1, T2>> converters = new Dictionary<Tuple<System.Type, System.Type>, convertbase<T1, T2>>();

        static public T2 Convert(T1 i)
        {
            var key = new Tuple<System.Type, System.Type>(typeof(T2), typeof(T1));
            if (!converters.ContainsKey(key))
            {

                var xassemblybuilder = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("xassembly"), System.Reflection.Emit.AssemblyBuilderAccess.Run);
                var xtype = xassemblybuilder.DefineDynamicModule("xmodule").DefineType("xtype", TypeAttributes.Public, typeof(convertbase<T1, T2>));
                var xfunction = xtype.DefineMethod("convert", MethodAttributes.Public | MethodAttributes.Virtual, typeof(T2), new System.Type[] { typeof(T1) });
                xtype.DefineMethodOverride(xfunction, typeof(convertbase<T1, T2>).GetMethod("convert"));

                var il = xfunction.GetILGenerator();

                il.DeclareLocal(typeof(T2));

                il.Emit(OpCodes.Newobj, typeof(T2).GetConstructor(System.Type.EmptyTypes));
                il.Emit(OpCodes.Stloc_0);

                (from z in typeof(T1).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 join y in typeof(T2).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_1);
                     il.Emit(OpCodes.Ldfld, typeof(T1).GetField(a));
                     il.Emit(OpCodes.Stfld, typeof(T2).GetField(a));
                 });

                (from z in typeof(T1).GetProperties().Select(a => new { name = a.Name, type = a.PropertyType })
                 join y in typeof(T2).GetProperties().Where(b => b.CanWrite).Select(a => new { name = a.Name, type = a.PropertyType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_1);
                     il.Emit(OpCodes.Callvirt, typeof(T1).GetProperty(a).GetGetMethod());
                     il.Emit(OpCodes.Callvirt, typeof(T2).GetProperty(a).GetSetMethod());
                 });


                (from z in typeof(T1).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 join y in typeof(T2).GetProperties().Where(b => b.CanWrite).Select(a => new { name = a.Name, type = a.PropertyType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_1);
                     il.Emit(OpCodes.Ldfld, typeof(T1).GetField(a));
                     il.Emit(OpCodes.Callvirt, typeof(T2).GetProperty(a).GetSetMethod());
                 });

                (from z in typeof(T1).GetProperties().Select(a => new { name = a.Name, type = a.PropertyType })
                 join y in typeof(T2).GetFields().Select(a => new { name = a.Name, type = a.FieldType })
                 on z equals y
                 select z.name).ToList().ForEach(a =>
                 {
                     il.Emit(OpCodes.Ldloc_0);
                     il.Emit(OpCodes.Ldarg_1);
                     il.Emit(OpCodes.Callvirt, typeof(T1).GetProperty(a).GetGetMethod());
                     il.Emit(OpCodes.Stfld, typeof(T2).GetField(a));
                 });

                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ret);

                xtype.CreateType();

                converters.Add(key, (convertbase<T1, T2>)xassemblybuilder.CreateInstance("xtype"));
            }
            return converters[key].convert(i);
        }

    }

    public abstract class convertbase<T1, T2>
    {
        public abstract T2 convert(T1 i);
    }
}

Compared to the original MSIL version at 100 million repetitions:

Delegate MSIL: 93.423 seconds vs Base Class MSIL: 91.814 seconds

At REALLY high volumes that is significant, and I am certain that someone better at MSIL than I could probably make it a bit faster still, but for my purposes the Linq version is more than sufficient as I find the MSIL versions a little hard to work in for the level of benefit in return.

20110509

better type conversion between similar objects

Friday I posted what is about the simplest possible way to automagicly convert between two objects that have mostly the same fields and properties but have no implicit conversion or common interface or base type.  It uses reflection and a little Linq, but it uses reflection every single time so it does not perform very well under load.  You can see that post here.

I wrote that as a quick hack to solve a specific, temporary problem a few weeks ago and I knew it wasn't going to be very efficient, but it didn't matter in that instance.  The best solutions in this sort of problem are MSIL assuming you cannot just change the classes to share dependencies, but MSIL is not something very many folks can read, and even fewer can write.

In .Net 4, you get some interesting additions/better documentation to Linq show you how to build expressions on the fly, so I wanted to take a stab at re-writing the converter that way.

The general idea is the same, use reflection to look for fields and writable properties then generate some action to sync them up, but there are several differences:
  • reflection is only used the first time a pair of types is converted
  • the actions are generated as Linq that is then compiled before storing in the converters set
  • added the ability to set a property to a field or field to property
  • added type checking
This is not going to perform as well as MSIL, but for a team with little MSIL experience it is going to be far more supportable and it seems to perform reasonably well.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace typeoverridedemostrater
{
    static class SuperConverter<T1, T2> where T2 : new()
    {

        private static Dictionary<Tuple<System.Type, System.Type>, Func<T1, T2>> converters = new Dictionary<Tuple<System.Type, System.Type>, Func<T1, T2>>();

        static public T2 Convert(T1 i)
        {
            var key = new Tuple<System.Type, System.Type>(typeof(T2), typeof(T1));
            if (!converters.ContainsKey(key))
            {

                ParameterExpression value = Expression.Parameter(typeof(T1), "value");
                ParameterExpression result = Expression.Parameter(typeof(T2), "result");
                var exprs = new List<Expression>();
                exprs.Add(Expression.Assign(result, Expression.New(typeof(T2))));

                exprs.AddRange((
                        from z in typeof(T2).GetProperties().Where(a => a.CanWrite)
                            .Select(b => new { name = b.Name, type = b.PropertyType }).Union(
                            typeof(T2).GetFields().Select(c => new { name = c.Name, type = c.FieldType }))
                        join y in typeof(T1).GetProperties().Where(a => a.CanWrite)
                            .Select(b => new { name = b.Name, type = b.PropertyType }).Union(
                            typeof(T1).GetFields().Select(c => new { name = c.Name, type = c.FieldType }))
                        on z equals y
                        select
                            Expression.Assign(Expression.PropertyOrField(result, z.name), Expression.PropertyOrField(value, z.name))
                        ).ToArray()
                    );
                exprs.Add(result);
                BlockExpression block = Expression.Block(variables: new[] { result }, expressions: exprs.ToArray());
                converters.Add(key, Expression.Lambda<Func<T1, T2>>(block, value).Compile());
            }
            return converters[key].Invoke(i);
        }
    }
}


the general flow is:
  1. if you don't already have a good converter
  2. create an input value and output result
  3. create an action to assign a new instance to the result variable
  4. add an assign action for every param/field that has a match between the types
  5. add an action for returning the result
  6. turn those into an expression block
  7. turn the block Lambda, then compiled to a TDelegate and store in the converters dictonary
  8. run the TDelegate from the dictionary


For 100,000 conversions the before/after is:

TotalMilliseconds = 1609.4059 vs TotalMilliseconds = 93.7518

20110506

Cheap type conversion for very similar objects

Ever get stuck between two API and have to keep converting between two almost identical sets of data objects because neither API can be modded at the moment?  If you can afford some performance penalty, this is a quick way to get fields and properties with the same names synced.

First you add some implicit type operators:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace typeoverridedemostrater
{
    class Class2
    {
        public string string1;
        public string string2;
        public string string3;
 
        public static implicit operator Class2(Class1 initialData)
        {
            return new SuperConverter<Class1Class2>().Convert(initialData);
        }
 
        public static implicit operator Class2(Class3 initialData)
        {
            return new SuperConverter<Class3Class2>().Convert(initialData);
        }
    }
}

After  you call the converter, you can add whatever specific conversions you need.

(EDIT - as Brooke pointed out, the real version of this was an extension to an existing class, not a class with an internal operator the code above was from the demo project I bashed out to explain the concept to another dev)

Then you use some reflection and linq to do the assignments in a separate class that you can re-use in as many type converters as you like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace typeoverridedemostrater
{
    class SuperConverter where T2 : new()
    {
        public T2 Convert(T1 i)
        {
            var temp = new T2();
 
            typeof(T1).GetProperties().ToList().Where(a => a.CanWrite).ToList().
                ForEach(b =>
                {
                    var z = temp.GetType().GetProperty(b.Name);
                    if (z != null) z.SetValue(temp, b.GetValue(i, null), null);
                });
            
            typeof(T1).GetFields().ToList().ToList().
                ForEach(b =>
                {
                    var z = temp.GetType().GetField(b.Name);
                    if (z != null) z.SetValue(temp, b.GetValue(i));
                });
 
            return temp;
        }
    }
}


Obviously this only works in some cases, and if your types do not match precisely you would have to make it a little more complex by checking for compatible types, or handling failure more gracefully, but it can save a ton of time in some cases.

20110504

Adding a WCF function to a service, in code, at runtime

Working on something last week I thought it might be a good idea to have an attribute that added an extra endpoint to a service at runtime.  I coded for a bit making decent progress, got stuck, and when I started to google I saw several discussions of it not being possible, and one discussion about how to do it by modifying the host (http://zamd.net/2010/02/05/adding-dynamic-methods-to-a-wcf-service/).  It turns out that after the service is running some things seem to be locked down that you would need to pull this trick off.

Remembering some similar issues in HttpModules/HttpApplications I started looking for a point to do the injection of a method while the service is in the middle of loading and I found ServiceBehavior.AddBindingParameters.  The other two methods don't seem to be at the right point in the sequence for the injection to work correctly.

WARNING: lots of trial & error based code ahead, I doubt this is correct in all situations, it does work on a REST POX service fairly well.  I am mostly writing this so I remember it, and so others can see it probably can be done.

First you have to make an attribute that you will use later to decorate your service implementation.  In this example the AddUI sub looks at the first operation for the current contract, copies a lot of it's general settings then adds the messages to an operation, then the operation to the contract.

Imports System.ServiceModel.Description
 
Public Class ExternalInvalidatorAttribute
    Inherits Attribute
    Implements IServiceBehavior
 
    Public Sub AddBindingParameters(ByVal serviceDescription As System.ServiceModel.Description.ServiceDescriptionByVal serviceHostBase As System.ServiceModel.ServiceHostBaseByVal endpoints As System.Collections.ObjectModel.Collection(Of System.ServiceModel.Description.ServiceEndpoint), ByVal bindingParameters As System.ServiceModel.Channels.BindingParameterCollectionImplements System.ServiceModel.Description.IServiceBehavior.AddBindingParameters
        For Each endpt In endpoints
            AddUI(endpt)
        Next
    End Sub
 
    Private Sub AddUI(ByRef endpt As ServiceEndpoint)
        Dim cd = endpt.Contract.Operations(0).DeclaringContract
        Dim od = New OperationDescription("invalidatorUI", cd)
 
        Dim inputMsg = New MessageDescription(cd.Namespace + cd.Name + "/invalidatorUI"MessageDirection.Input)
        Dim mpd = New MessagePartDescription("a", endpt.Contract.Namespace)
        mpd.Index = 0
        mpd.MemberInfo = Nothing
        mpd.Multiple = False
        mpd.ProtectionLevel = Net.Security.ProtectionLevel.None
        mpd.Type = GetType(System.String)
        inputMsg.Body.Parts.Add(mpd)
        od.Messages.Add(inputMsg)
 
        Dim outputMsg = New MessageDescription(cd.Namespace + cd.Name + "/invalidatorUIResponse"MessageDirection.Output)
        outputMsg.Body.ReturnValue = New MessagePartDescription("invalidatorUIResult", cd.Namespace) With {.Type = GetType(System.String)}
        od.Messages.Add(outputMsg)
 
        od.Behaviors.Add(New DataContractSerializerOperationBehavior(od))
        od.Behaviors.Add(New System.ServiceModel.Web.WebGetAttribute() With {.UriTemplate = "/invalidator/{a}"})
        od.Behaviors.Add(New System.ServiceModel.OperationBehaviorAttribute())
        Dim dc = New DasOP()
 
        od.Behaviors.Add(dc)
 
        cd.Operations.Add(od)
    End Sub
 
 
#Region "not needed"
 
    Public Sub ApplyDispatchBehavior(ByVal serviceDescription As System.ServiceModel.Description.ServiceDescriptionByVal serviceHostBase As System.ServiceModel.ServiceHostBaseImplements System.ServiceModel.Description.IServiceBehavior.ApplyDispatchBehavior
    End Sub
 
    Public Sub Validate(ByVal serviceDescription As System.ServiceModel.Description.ServiceDescriptionByVal serviceHostBase As System.ServiceModel.ServiceHostBaseImplements System.ServiceModel.Description.IServiceBehavior.Validate
    End Sub
 
#End Region
 
End Class

Since there is no function in the service implementation the default invoker call would error with nothing to act upon, so the DasOP custom operation behavior is substituted for the default.  Looking at it's apply dispatch sub below you can see it is just a crutch to a custom invoker.  You don't have to do this, but if you don't you have to deal with the message objects by hand, and they are not really that friendly. 

Imports System.ServiceModel.Description
 
Public Class DasOp
    Inherits Attribute                                  'this makes it a decorator
    Implements IOperationBehavior                       'this makes it get called for applybehaviour
 
    Public Sub ApplyDispatchBehavior(ByVal operationDescription As System.ServiceModel.Description.OperationDescriptionByVal dispatchOperation As System.ServiceModel.Dispatcher.DispatchOperationImplements System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior
        dispatchOperation.Invoker = New InvalidatorInvoker()    'this invoker actually does the work, it needs a reference to the other cache objects so it can meddle in their cache arrays
    End Sub
 
#Region "not used"
    Public Sub AddBindingParameters(ByVal operationDescription As System.ServiceModel.Description.OperationDescriptionByVal bindingParameters As System.ServiceModel.Channels.BindingParameterCollectionImplements System.ServiceModel.Description.IOperationBehavior.AddBindingParameters
        'not needed
    End Sub
 
    Public Sub ApplyClientBehavior(ByVal operationDescription As System.ServiceModel.Description.OperationDescriptionByVal clientOperation As System.ServiceModel.Dispatcher.ClientOperationImplements System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior
        'not needed
    End Sub
 
    Public Sub Validate(ByVal operationDescription As System.ServiceModel.Description.OperationDescriptionImplements System.ServiceModel.Description.IOperationBehavior.Validate
        'not needed
    End Sub
#End Region
 
End Class

Finally you make the invoker, it doesn't really invoke anything, since nothing actually exists to invoke, but it allocates and input and returns a result like their was, so the rest of the WCF seems not to notice the difference.

Imports System.ServiceModel.Dispatcher
Imports System.Xml.Linq
Imports System.Text.RegularExpressions
 
Public Class InvalidatorInvoker
    Implements IOperationInvoker
 
    Public Function AllocateInputs() As Object() Implements System.ServiceModel.Dispatcher.IOperationInvoker.AllocateInputs
        Return {Nothing}    'reserve a spot for some input
    End Function
 

   Public Function Invoke(ByVal instance As ObjectByVal inputs() As ObjectByRef outputs() As ObjectAs Object Implements System.ServiceModel.Dispatcher.IOperationInvoker.Invoke
        outputs = New Object(-1) {}     'return an empty array here, MSDN does not elaborate as to why
        Return "Result"
   End Function
 
#Region "not needed"
 
    Public Function InvokeBegin(ByVal instance As ObjectByVal inputs() As ObjectByVal callback As System.AsyncCallbackByVal state As ObjectAs System.IAsyncResult Implements System.ServiceModel.Dispatcher.IOperationInvoker.InvokeBegin
        Return Nothing
    End Function
 
    Public Function InvokeEnd(ByVal instance As ObjectByRef outputs() As ObjectByVal result As System.IAsyncResultAs Object Implements System.ServiceModel.Dispatcher.IOperationInvoker.InvokeEnd
        Return Nothing
    End Function
 
#End Region
 
    Public ReadOnly Property IsSynchronous As Boolean Implements System.ServiceModel.Dispatcher.IOperationInvoker.IsSynchronous
        Get
            Return True     'disable async
        End Get
    End Property
 
End Class

It isn't pretty, but it works.

20110328

Microsoft.Web.Infrastructure + System.Web.PreApplicationStartMethod

What follows is interesting & a neat trick, but I do not claim that it is a good idea to do this in production code.  It may be useful, it may not.

I have been playing around with a few of the new bits that are available for .NET web development recently and I came across a neat trick.  I had a project that I wanted to debug, but I didn't have access to the source directly and the app itself was handling the error and in the process eating some of the detail I needed.

I made a httpmodule that was decorated with System.Web.PreApplicationStartMethod This is a framework 4 bit that allows a httpmodule to run a shared sub BEFORE all the stack gets built and locked in place.

I then took and used reflection to load and invoke Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule.  This allows the httpmodule to place itself in the modules collection without altering the web config.  Loading it through reflection allows me to just drag the dll into the bin folder along with the httpmodule dll.  This is handy because web.infrastructure is part of the MVC framework and the problem I was having was on a non-mvc machine.

A little poking about in reflector and I came up with this function to get the existing event handlers



Dim t As Type = target.[GetType]()
Public Function GetEventSubscribers(ByVal target As Object, ByVal eventName As String) As [Delegate]()
    Dim w = CType(t.GetField("_events", BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.NonPublic).
        GetValue(target), System.ComponentModel.EventHandlerList)
    Dim k = t.GetFields(BindingFlags.[Static] Or BindingFlags.Instance Or BindingFlags.NonPublic).
        Where(Function(x) x.Name.StartsWith("Event" & eventName)).Select(Function(x) x.GetValue(target)).ToList()
    Dim d() As [Delegate] = k.SelectMany(Function(x)
                                             If w(x) Is Nothing Then
                                                 Return New [Delegate]() {}
                                             Else
                                                 Return w(x).GetInvocationList()
                                             End If
                                         End Function).ToArray
    Return d
End Function

If you pass the httpapplication instance to it with an eventname you get all the registered handler delegates, which will allow you to call .removeeventhandler() on each of them.  

If you do that to the error event, then add your own handler, then re-add the pre-existing delegates in the correct order then your handler fires first, before any of the other handlers has a chance to mangle the even state and the rest of the application seems to be none the wiser as long as you don't alter the even state yourself.

In my example I just put a trace in that wrote to a text file and after a few passes at the broken bits I got a nice clear picture of what was going on.

The approach seems to work in ASPX, MVC, WCF and Sharepoint and only involves copying a couple dlls to the bin directory in the way of altering the original project.

Again, I haven't used this too much yet, so your mileage may vary, but even if it doesn't always work I think it is an interesting approach to spy on a misbehaving build without changing too many variables.

20110213

Get Well Mike Jennings

A good friend of the family is in ICU with a brain tumor. I have set up a facebook page for people to update / comment / share news as facebook is something simple for most to use and I am away for work most of the week.

If you do not use facebook, the short version of the story is that he didn't know he had it until they found it after he had been rushed to the hospital thursday. He has had surgery and is stable the last I heard yesterday evening.

Get Well Mike Jennings

Firefox Feedly RSS option

If you use Firefox with a RSS button and want the default RSS page to offer a Feedly option here is what you need to do: go to the about:c...