Notes from the trenches.

Best Hack

Posted: April 15th, 2009 | Author: admin | Filed under: code | Tags: , , , , , , , | No Comments »

I was just thinking what my best hack has been and I think it’s the fix for the following scenario.

I was refactoring the RSinteract source code to get rid of some duplicated classes that had over the course of a, shall we say, rigourous development schedule got disparate. Some classes were used from one set some from the other. I merged them into the common library and deleted all the old ones. This was fine until we ran an old report that had filters on it. Because the types had been serialized into the custom RDL of the report they had the old namespace stored there. Which threw an error when deserializing with the new hierarchy.

So what to do… I had a brainwave:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text; 
   4:  
   5: namespace Ics.Reporting.Data
   6: {
   7:     [Serializable]
   8:     public class Dimension : Ics.Reporting.Common.Data.Dimension
   9:     {
  10:         //Proxy class to fix issues with old reports containing a reference to this class which has
  11:         //been moved to Ics.Reporting.Common.Data.Dimension
  12:     }
  13: } 

The empty proxy class in the old namespace that inherits from the new class. Leave a comment as to why. Et voila! No more broken old reports.

What’s your best hack imaginary readers?


Experiences with Unity

Posted: February 18th, 2009 | Author: admin | Filed under: code, personal | Tags: , , , , , , , , , | No Comments »

I’ve been very busy over the last few weeks. The new RSinteract beta is due out at the end of this month (several clients are currently using it with no problems) and it looks sweeeet! Pretty proud of my contribution to that particular project and kind of sad that I’m no longer working on it. I’m now involved on a new project involving a certain sporting event taking place in 2012. It’s quite exciting and I’ve been given a fairly important part of the architecture to work on.

Finally, lots of new technology and challenges to overcome for me. One of these is dependency injection using an IoC container. I’ve worked on projects that have used it them and have understood the general principles but never have I had full control of it – it’s always been there already. This time I’m learning it properly myself. The technology that has been chosen is Microsoft’s Unity 1.2 which ships with the Enterprise Library 4.1 (Oct 2008 release). At first glance Unity appears overly complex because the documentation for it is – as Microsoft love to do – overly complicated and tries to show you everything on one page. For example:

   1: <?xml version="1.0" encoding="utf-8" ?> 
   2: configuration>
   3:  
   4: configSections>
   5:  <section name="unity"
   6:            type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
   7:                 Microsoft.Practices.Unity.Configuration, Version=1.1.0.0,
   8:                 Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   9: /configSections>
  10:  
  11: unity>
  12:  
  13:  <typeAliases>
  14:  
  15:    <!-- Lifetime manager types -->
  16:    <typeAlias alias="singleton"
  17:         type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
  18:               Microsoft.Practices.Unity" />
  19:    <typeAlias alias="external"
  20:         type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,
  21:               Microsoft.Practices.Unity" />
  22:  
  23:    <!-- User-defined type aliases -->
  24:    <typeAlias alias="IMyInterface"
  25:         type="MyApplication.MyTypes.MyInterface, MyApplication.MyTypes" />
  26:    <typeAlias alias="MyRealObject" 
  27:         type="MyApplication.MyTypes.MyRealObject, MyApplication.MyTypes" />
  28:    <typeAlias alias="IMyService"
  29:         type="MyApplication.MyTypes.MyService, MyApplication.MyTypes" />
  30:    <typeAlias alias="MyDataService"
  31:         type="MyApplication.MyTypes.MyDataService, MyApplication.MyTypes" />
  32:    <typeAlias alias="MyCustomLifetime" 
  33:         type="MyApplication.MyLifetimeManager, MyApplication.MyTypes" />
  34:  
  35:  </typeAliases>
  36:  
  37:  <containers>
  38:  
  39:    <container name="containerOne">
  40:  
  41:      <types>
  42:  
  43:        <!-- Type mapping with no lifetime – defaults to "transient" -->  
  44:        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass" />
  45:  
  46:        <!-- Type mapping using aliases defined above -->  
  47:        <type type="IMyInterface" mapTo="MyRealObject" name="MyMapping" />
  48:  
  49:        <!-- Lifetime managers specified using the type aliases -->
  50:        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
  51:          <lifetime type="singleton" /> 
  52:        </type>
  53:        <type type="IMyInterface" mapTo="MyRealObject" name="RealObject">
  54:          <lifetime type="external" />
  55:        </type>
  56:  
  57:        <!-- Lifetime manager specified using the full type name -->
  58:        <!-- Any initialization data specified for the lifetime manager -->
  59:        <!-- will be converted using the default type converter -->
  60:        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
  61:          <lifetime value="sessionKey"
  62:                    type="MyApplication.MyTypes.MyLifetimeManager,
  63:                          MyApplication.MyTypes" />
  64:        </type>
  65:  
  66:        <!-- Lifetime manager initialization using a custom TypeConverter -->
  67:        <type type="IMyInterface" mapTo="MyRealObject" name="CustomSession">
  68:          <lifetime type="MyCustomLifetime" value="ReverseKey"
  69:                    typeConverter="MyApplication.MyTypes.MyTypeConverter,
  70:                                   MyApplication.MyTypes" />
  71:        </type>
  72:  
  73:        <!-- Object with injection parameters defined in configuration -->
  74:        <!-- Type mapping using aliases defined above -->  
  75:        <type type="IMyService" mapTo="MyDataService" name="DataService">
  76:          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
  77:                                     Microsoft.Practices.Unity.Configuration">
  78:            <constructor>
  79:              <param name="connectionString" parameterType="string">
  80:                <value value="AdventureWorks"/>
  81:              </param>
  82:              <param name="logger" parameterType="ILogger">
  83:                <dependency />
  84:              </param>
  85:            </constructor> 
  86:            <property name="Logger" propertyType="ILogger" />
  87:            <method name="Initialize">
  88:              <param name="connectionString" parameterType="string">
  89:                <value value="contoso"/>
  90:              </param>
  91:              <param name="dataService" parameterType="IMyService">
  92:                <dependency />
  93:              </param>
  94:            </method>
  95:          </typeConfig>
  96:        </type>
  97:  
  98:      </types>
  99:  
 100:      <instances>
 101:        <add name="MyInstance1" type="System.String" value="Some value" />
 102:        <add name="MyInstance2" type="System.DateTime" value="2008-02-05T17:50:00"  />
 103:      </instances>
 104:  
 105:      <extensions>
 106:        <add type="MyApp.MyExtensions.SpecialOne" />
 107:      </extensions>
 108:  
 109:      <extensionConfig>
 110:        <add name="MyExtensionConfigHandler"
 111:             type="MyApp.MyExtensions.SpecialOne.ConfigHandler" />
 112:      </extensionConfig>
 113:  
 114:    </container>
 115:  
 116:    <!-- ... more containers here ... -->
 117:  
 118:  </containers>
 119:  
 120: </unity>
 121:  
 122: </configuration>

(Note this documentation is from 1.1)

Now I’m unit testing from the ground up. I don’t care about most of this stuff. I need the simplest implementation to start with. So all I really need in my config file is: the unity section declaration, a type alias and the container.  Like so:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <configSections>
   4:     <section name="unity"
   5:                type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
   6:                  Microsoft.Practices.Unity.Configuration, Version=1.2.0.0,
   7:                  Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   8:   </configSections>
   9:   <unity>
  10:     <typeAliases>
  11:       <!--IService-->
  12:       <typeAlias alias="IService"
  13:                  type="Project.Services.Contract.IService,
  14:                  Project.Services" />
  15:       <typeAlias alias="MockService"
  16:                  type="Project.Mocks.FakeService,
  17:                  Project.Mocks" />
  18:     </typeAliases>
  19:     <containers>
  20:       <!--Service is Mocked-->
  21:       <container name="UnitTest">
  22:         <types>
  23:           <type type="IService" mapTo="MockService" />
  24:         </types>
  25:       </container>
  26:     </containers>
  27:    </unity>
  28: </configuration>

That’s it. (Obviously any types referenced here need their assemblies referenced in the unit test project). Why isn’t there a good tutorial that points this out? It seems like Microsoft tripping themselves over again. I’ve found this with other parts of the Enterprise Library too. Thank god for StackOverflow!