Archive for July, 2010

Using The Dynamic Keyword To Avoid Difficulties With Generics

15 commentsWritten on July 16th, 2010 by
Categories: C#, Code Quality

A coworker was working on some kind of base EntityBuilder class to use in his tests.  One of the requirements of the EntityBuilder class was that it would need to automatically set the ID of an entity to a ‘real’ value (as in: not the default value of the type).  The EntityBuilder would use some kind of IdGenerator based on the type of the ID of the entity.   First of all, the example i’m gonna show is highly simplified and might not look like it makes much sense, but it’s only to illustrate some C# stuff with regards to generics and the dynamic keyword.  So bear with me, and just focus on the language details :)

Suppose you’ve got something like this:

    public abstract class Entity<TId>

    {

        public virtual TId Id { get; set; }

    }

 

    public interface IIdGenerator<TId>

    {

        TId GenerateId();

    }

 

    public class IntIdGenerator : IIdGenerator<int>

    {

        private static int lastIssuedId;

 

        public int GenerateId()

        {

            return ++lastIssuedId;

        }

    }

 

    public class GuidIdGenerator : IIdGenerator<Guid>

    {

        public Guid GenerateId()

        {

            return Guid.NewGuid();

        }

    }

 

The idea was to write the EntityBuilder somewhat along these lines:

    public abstract class TestEntityBuilder<TEntity, TId> where TEntity : Entity<TId>

    {

        public TEntity Build()

        {

            var entity = CreateEntityWithDefaultProperties();

            entity.Id = GetIdGeneratorFor(typeof(TId)).GenerateId();

            return entity;

        }

 

        protected abstract TEntity CreateEntityWithDefaultProperties();

 

        private IIdGenerator<TId> GetIdGeneratorFor(Type type)

        {

            if (type == typeof(int))

            {

                return new IntIdGenerator();

            }

 

            return new GuidIdGenerator();

        }

    }

 

Of course, that doesn’t even compile… you’ll get the following compiler errors:

error CS0266: Cannot implicitly convert type 'MyProject.IntIdGenerator' to 'MyProject.IIdGenerator<TId>'. An explicit conversion exists (are you missing a cast?)
error CS0266: Cannot implicitly convert type 'MyProject.GuidIdGenerator' to 'MyProject.IIdGenerator<TId>'. An explicit conversion exists (are you missing a cast?)

So, how exactly do you get this working with generics? That’s when he asked for my help, and i didn’t know the answer either… i’ve struggled with this exact problem in a few previous situations and i never really got a clean solution either.  But then i thought “wait, can’t we just avoid the problems with generics through the dynamic keyword?”

We changed the code to look like this:

    public abstract class TestEntityBuilder<TEntity, TId> where TEntity : Entity<TId>

    {

        public TEntity Build()

        {

            var entity = CreateEntityWithDefaultProperties();

            entity.Id = GetIdGeneratorFor(typeof(TId)).GenerateId();

            return entity;

        }

 

        protected abstract TEntity CreateEntityWithDefaultProperties();

 

        private dynamic GetIdGeneratorFor(Type type)

        {

            if (type == typeof(int))

            {

                return new IntIdGenerator();

            }

 

            return new GuidIdGenerator();

        }

    }

 

We just changed the return type of the GetIdGeneratorFor method to ‘dynamic’, and the call to the GenerateId method is now a dynamic call instead of a normal method call.  And it works.  No messing around with generics voodoo, no (direct) usage of reflection either.  Just clean code.

I’ll probably use this trick a lot more times in the future when i run into the limitations of generics :)

I Finally Caved: I’m On Twitter

8 commentsWritten on July 15th, 2010 by
Categories: About The Blog

Ok... i know what i said before. And i don't know yet whether i was right or wrong. But it is starting to feel like i'm missing out on some good conversations due to not being on twitter so i figured "what the hell, i'm gonna give it a shot". So i've created an account (@davybrion) and i'm just gonna see how it goes. If i like it, i'll keep using it and i'll gladly state that i was wrong about the whole thing. If i don't like it, i'll get rid of the account and i'll let you know why :) . But however it's gonna turn out to be, at least this time it'll be an informed decision.

So... any tips from you twitter addicts on how to keep the signal-to-noise ratio down and how to make the whole experience as valuable as possible?

What’s Wrong With This Picture?

7 commentsWritten on July 14th, 2010 by
Categories: What's Wrong With This Picture

Actually, this time it’s pictures instead of just one… 2 of my coworkers pointed me to a piece of code that they thought was pretty ugly.  Much to my amusement, i spotted something that i think is worth a post :)

wr1

wr2

500 Posts

1 Comment »Written on July 13th, 2010 by
Categories: About The Blog

So this is my 500th post on this blog.  I know i said that i would end the tradition of posting the most popular recent (as in: within the last 100 posts) posts when i hit 400 but since 500 is such a nice number, i think it’s alright if i hit you guys with another link bonanza.  So i’m gonna post the links to the top 10 most popular posts of all time, as well as the top 10 most popular posts of the last 100.

Top 10 All Time:

  1. Career Advice For Young Developers
  2. At This Point, I’d Prefer Java Developers Over .NET Developers
  3. NHibernate Mapping Examples (pretty outdated by now though)
  4. Build Your Own Data Access Layer Series
  5. Upgrading To NHibernate 2.1 (this is what happens when people are too lazy to read exception messages)
  6. A Reading Guide To Becoming A Better Developer
  7. Data Access Layer With NHibernate
  8. Managing Your NHibernate Sessions
  9. Sending NHibernate Entities Over The WCF Wire (i wish i never wrote this)
  10. Request Response Service Layer Series

Top 10 Of The Last 100:

  1. Why You Shouldn't Expose Your Entities Through Your Services
  2. Using NHibernate In Your Service Layer
  3. Hey Microsoft, Our Databases Aren't Services!
  4. Unit Testing An NHibernate Application
  5. Avoiding Leaking Connections With NHibernate And TransactionScope
  6. Agatha Vs NServiceBus
  7. Do You Know What's Really Going On?
  8. Dependency Injection Inversion Rejection
  9. Real World Benefits From Loose Coupling, Inversion Of Control And Dependency Injection
  10.  Virtual Method Performance Penalty

So… on to the next 100 i guess :)

Resharper 5.1’s Test Runner Is Broken

46 commentsWritten on July 13th, 2010 by
Categories: resharper

I used to be very happy with pretty much everything JetBrains released, but lately they seem to be having some serious quality issues with their Resharper product.  The 5.0 release was pretty much unusable for us due to a stupid bug in their Silverlight support.  It was fixed in the 5.1 EAP builds, but the newly released 5.1 version has another major (IMO) problem when it comes to running tests:

resharper_fail

It no longer runs inherited tests.  Which is especially annoying to us because we use inherited tests to make sure that our NHibernate CRUD operations work.  We also use the inherited tests pattern for some other things, but that means we’re pretty much screwed now.

The bug has already been reported but since they closed the Early Access Program due to the release of 5.1, i guess we’re gonna have to wait quite a while before we can get our hands on a version that has a usable test runner.

If anyone from the Resharper team reads this: please tell me how on earth something like this could break in a bugfix release?  You sell software for continuous integration, for code coverage, for running tests.  If you’d actually use these things and wrote correct tests then this wouldn’t have happened…