Update on inheriting base type mappings with AutoMapper

Several months ago I wrote this post which shows an extension method for inheriting the mappings on a base type for a child type in AutoMapper.  Since then I have had a few comments on the post which led me to make a small update. One of the assumptions I made in my implementation was that when inheriting base type mappings both of your mapping types will have their base types in the parent mapping. For example:

Mapper.CreateMap<SourceBaseClass, DestBaseClass>()
    .ForMember(x => x.BasePropTwo, m => m.MapFrom(x => x.BaseProp2));
 
Mapper.CreateMap<SourceChildClass, DestChildClass>()
    .ForMember(x => x.ChildPropTwo, m => m.MapFrom(x => x.ChildProp2))
    .InheritMappingFromBaseType();

However, there are scenarios where you may have one type that is mapping to both a parent and child type and would still want to inherit the parent mapping for the child mapping. If you try this with my previous code it would look like this but not work.

Mapper.CreateMap<SourceClass, DestBaseClass>()
    .ForMember(x => x.BasePropTwo, m => m.MapFrom(x => x.BaseProp2));
 
Mapper.CreateMap<SourceClass, DestChildClass>()
    .ForMember(x => x.ChildPropTwo, m => m.MapFrom(x => x.ChildProp2))
    .InheritMappingFromBaseType();

In order to support this scenario I updated the extension method to take an optional enum which specifies if you want to inherit a mapping that has a base type for the source type, destination type or both.

public enum WithBaseFor
{
    Source,
    Destination,
    Both
}

public static class Inheritance
{
    public static void InheritMappingFromBaseType<TSource, TDestination>(this IMappingExpression<TSource, TDestination> mappingExpression,
                                                                         WithBaseFor baseFor = WithBaseFor.Both)
    {
        var sourceType = typeof (TSource);
        var destinationType = typeof (TDestination);
        var sourceParentType = baseFor == WithBaseFor.Both || baseFor == WithBaseFor.Source
                                   ? sourceType.BaseType
                                   : sourceType;

        var destinationParentType = baseFor == WithBaseFor.Both || baseFor == WithBaseFor.Destination
                                        ? destinationType.BaseType
                                        : destinationType;

        mappingExpression
            .BeforeMap((x, y) => Mapper.Map(x, y, sourceParentType, destinationParentType))
            .ForAllMembers(x => x.Condition(r => NotAlreadyMapped(sourceParentType, destinationParentType, r)));
    }

    private static bool NotAlreadyMapped(Type sourceType, Type desitnationType, ResolutionContext r)
    {
        return !r.IsSourceValueNull &&
               Mapper.FindTypeMapFor(sourceType, desitnationType).GetPropertyMaps().Where(
                   m => m.DestinationProperty.Name.Equals(r.MemberName)).Select(y => !y.IsMapped()).All(b => b);
    }
}

Using this new code the above mapping becomes

Mapper.CreateMap<SourceClass, DestBaseClass>()
    .ForMember(x => x.BasePropTwo, m => m.MapFrom(x => x.BaseProp2));

Mapper.CreateMap<SourceClass, DestChildClass>()
    .ForMember(x => x.ChildPropTwo, m => m.MapFrom(x => x.ChildProp2))
    .InheritMappingFromBaseType(WithBaseFor.Destination);

There is one caveat to using my InheritMappingFromBaseType extension method that was discovered since my original post … it is not compatible with the Mapper.AssertConfigurationIsValid() call. It will cause this function to fail even though your mapping will work fine. I haven’t had a chance to figure out if there is a way around this but if anyone has an idea I would love to hear it.

I published the updated code and a sample project showing its use to the InheritedAutoMapper GitHub page. Feel free to grab the code and fork it to your liking.

Posted in AutoMapper, github | Leave a comment

Chutzpah 1.1.0 Released

A new version of Chutzpah is now live on Visual Studio Gallery and CodePlex.

This release contains the following changes:

  • Added a “Run JS Tests in Browser” menu option inside of Visual Studio. This will open your default browser and run the selected QUnit test file.
  • Automatically save the test file in Visual Studio when you choose “Run JS Tests”
  • Added keyboard shortcut support for Visual Studio
    • Bind a shortcut to the ProjectAndSolutionsContextMenus.Project.RunJSTests command to run JS tests
    • Return line and column position for failed tests when you run a test JS file directly.
    • Upgraded to PhantomJS 1.2
    Posted in Chutzpah, Open Source | Leave a comment

    A combined Mercurial and Git PowerShell Prompt

    A while ago I posted the code I use to create a custom PowerShell prompt to show the status of my Mercurial repositories. Since then I have also started using Git so I updated my prompt to work for both. I find this prompt very convenient since it quickly shows what branch you are in as well as what pending changes you have in your working directory.

    Here is the updated code:

    if (test-path function:\prompt) {
       $oldPrompt = ls function: | ? {$_.Name -eq "prompt"}
       remove-item -force function:\prompt
     }
     function prompt {
      function getGitStatus {
      $branch = git branch 2>&1
      if($branch.Exception -eq $null) {
        $status = "git"
        $branch | foreach {
          if ($_ -match "^\*(.*)"){
            $status += $matches[1]
          }
        }
    
        $untracked = 0
        $updates = 0
        $deletes = 0
        $addsIndex = 0
        $deletesIndex =0
        $updatesIndex = 0
    
        git status --porcelain | foreach {
          if($_ -match "^([\w?]|\s)([\w?])?\s*") {
            switch ($matches[1]) {
              "A" {$addsIndex++ }
              "M" {$updatesIndex++ }
              "D" {$deletesIndex++ }
              "?" {$untracked++ }
            }
            switch ($matches[2]) {
              "A" {$adds++ }
              "M" {$updates++ }
              "D" {$deletes++ }
             }
          }
        }
        $status += " a:" +$addsIndex
        if($adds -gt 0) {
          $status += "($adds)"
        }
    
        $status += " m:" +$updatesIndex
        if($updates -gt 0) {
          $status += "($updates)"
        }
    
        $status += " d:" +$deletesIndex
        if($deletes -gt 0) {
          $status += "($deletes)"
        }     
    
        $status += " ?:$untracked"
        return $status
      }
      else {
        return $false
      }
    }
    
      function getHgStatus {
        $summary = hg summary 2>&1
        if($summary.Exception -eq $null) {
          $regex = "(?si)(parent:(?<parent>.*?)(\n|\r)+.*?)(branch:(?<branch>.*)\s)(commit:(?<commit>.*)\s)(update:(?<update>.*))";
          $summary = [System.String]::Join([System.Environment]::NewLine,$summary)
          $res = $summary -match $regex
          $status = "hg {0} c:{1}" -f $matches["branch"].Trim(), $matches["commit"].Trim()
          return $status
       }
       else {
        return $false
       }
      }
    
      $status = getGitStatus
      if(-not $status) {
          $status = getHgStatus
      }
      $host.ui.rawui.WindowTitle = (get-location).Path
      if($status) {
        write-host ($status) -NoNewLine -ForegroundColor Green
        write-host (">") -NoNewLine -ForegroundColor Green
      }
      else {
        & $oldPrompt
      }
      return " "
    }

    After adding this prompt to your profile when you are in a git repository you will see this:

    This is more complex than the Mercurial prompt since git has the concept of a staging area. The number not in parentheses is the “staged” value and the number in parentheses is the unstaged value. So in the prompt above the repository has 1 modification staged and one unstaged.

    When you are in a Mercurial repository you will see this:

    hgPrompt

    Posted in Git, Mercurial, PowerShell | Leave a comment

    Making linking between anchors in an IFrame work in Firefox 4 and above

    In Firefox 4 a security fix was added which prevents linking between anchors within an IFrame that does not have scroll bars. This change breaks the scenario where you have an IFrame that has a “Go To Top” link (<a href=”top”>Go to top</a>) which links to an anchor tag (<a name=”#top” />) at the top of the IFrame.  If this IFrame does not have scroll bars then clicking the link will scroll the parent page to bring the anchor into view. This can be a security issue which is why Firefox is the first browser to block it.  However, I believe they should have added an exception for the case when the IFrame and the containing page satisfy the Same Origin Policy.

    I worked around this limitation by adding the following code to my IFrame (my implementation uses jQuery) which will override the anchor link functionality and scroll the window programmatically. This code makes use of the window.parent property which means it is subject to the Same Origin Policy.

    $(function(){
      $("a").each(function (){
        var link = $(this);
        var href = link.attr("href");
        if(href && href[0] == "#")
        {
          var name = href.substring(1);
          $(this).click(function() {
            var nameElement = $("[name='"+name+"']");
            var idElement = $("#"+name);
            var element = null;
            if(nameElement.length > 0) {
              element = nameElement;
            } else if(idElement.length > 0) {
              element = idElement;
            }
    
            if(element) {
              var offset = element.offset();
              window.parent.scrollTo(offset.left, offset.top);
            }
    
            return false;
          });
        }
      });
    });

    Posted in JavaScript | 19 Comments

    Chutzpah – A JavaScript Test Runner Released

    I just released to CodePlex and the Visual Studio Gallery a new project called Chutzpah (hutz·pah). Chutzpah is an open source JavaScript unit test runner which helps you integrate JavaScript unit testing into your website. It enables you to run JavaScript unit tests from the command line and from inside of Visual Studio. It also supports running in the TeamCity continuous integration server.

    Backstory

    About nine months ago I asked a question on StackOverflow about whether there were any tools/extensions which integrated into Visual Studio to run JavaScript unit tests. At that time there were no good solutions provided which led me to investigate creating my own tool. I explored many options but eventually I found the PhantomJS headless browser to help drive the tests.  After a couple weeks of development Chutzpah was born.

    What does Chutzpah do?

    Chutzpah is both a Visual Studio extension and a command line utility.

    As a Visual Studio extension:

    It allows you to run your JavaScript tests without leaving the IDE. It adds a context menu option to run tests directly from a source file.

    RightMenu

    It logs test results to both the Error list and the Output window.

    errorWindow

    outputWindow

    As a command line utility:

    It allows you to easily integrate test results into your build

    commandLine

    It also has support for the TeamCity continuous integration server so that you get detailed test output on every build.

    How to use it?

    Chutzpah is really easy to use, given QUnit tests (it only supports QUnit for now) you can run Chutzpah on the test harness HTML file and it will output the results. Chutzpah also supports running the tests directly from the JavaScript file as long as you add reference comments to the top of your test file.

    For example given two files test.js (QUnit tests file) and code.js (implementation file).

    code.js

    var mathLib = {
        add5: function (a) {
            return a + 5;
        }
    }

    test.js

    /// <reference path="code.js" />
    
    test("will add 5 to number", function () {
        var res = mathLib.add5(10)
    
        equals(res, 15, "should add 5");
    });

    You can run the tests by right clicking and choosing “Run JS Test” if you are using the Visual Studio plugin, otherwise you can execute Chutzpah from the command line:

    .\chutzpah.console.exe test.js

    Community Support

    I am really excited about releasing Chutzpah as an open source project with the hope of garnering support from the community. I would love to get feedback, bug reports, feature requests and code contributions. If you are interested in working on Chutzpah fork the code and get hacking.

    Future Plans Ideas

    At this stage I have many ideas of what features should come next for Chutzpah but outside of bug fixes I have no solid plans yet. Here are several ideas floating around in my head…

    1. Support other JavaScript unit test frameworks besides QUnit
    2. Expand past only using PhantomJS as the headless browser, possibly working with things like JsTestDriver or EnvJS.
    3. Be able to run individual tests instead of just a whole file.
    4. Add better IDE support like the Resharper 6 QUnit functionality.
    5. Add scanning for test files within a whole project hierarchy
    6. Support proxy servers
    7. Capture more detailed information from each test
    8. Integrate with existing test runners like MSTest or TestDriven.NET
    9. Add NuGet support
    Posted in Chutzpah, JavaScript, Open Source, Testing | 6 Comments