Register Login

 

Welcome to the Coach Factor blog. Here you will find all of our ideas on software development. Subscribe at  http://blog.nventive.net.

# Saturday, March 29, 2008

We've covered a lot so far with Part 1, Part 2, Part 3 and Part 4 of this adventure with extension methods.

Looking back at it, there are some nifty features and side effects that might have been overlooked.

With the magic of generic methods and compiler type inference, we are able to get a pretty discoverable and predictable api.

Let's look at the test first:

  [Fact]

  public void GetProperty()

  {

    DateTime now = DateTime.Now;

 

    Assert.Equal(now.Day, now.Reflection().GetProperty("Day"));

  }

What's in there? Well first we see that there is a Reflection() extension point, and this typed extension point has a GetProperty method. This makes it really EASY to figure out what can be done by reflection.

What should the code look like?

Let's start by the extension point class that will scope all available reflection methods:

  public class ReflectionExtensionPoint

  {

    public T Instance { get; set; }

  }

The ReflectionExtensionPoint class is generic so it can hold the type for which we want to use reflection. So we don't have to instantiate it manually all the time, we can create an extension method that will create such an instance

  public static class ReflectionExtension

  {

    public static ReflectionExtensionPoint Reflection(this T instance)

    {

      return new ReflectionExtensionPoint { Instance = instance };

    }

  }

Here lies all the magic. Since the method is generic and there are no constraints define, we can use the Reflection extension method on anything. Furthermore, there is no need to specify the generic type argument as it is automatically inferred by the compiler

This allows for a pretty compact syntax as shown here:

  [Fact]

  public void ReflectionExtensionPoint()

  {

    DateTime now = DateTime.Now;

 

    ReflectionExtensionPoint<DateTime> extensionPoint = now.Reflection();

 

    Assert.NotNull(extensionPoint);

    Assert.Equal(now, extensionPoint.Instance);

  }

Now that we have an extension point almost for free that represents a clear and very predictable subset of functionality, we can extend-the-extension-point to add additional behaviors.

  public static class ReflectionExtension

  {

    public static ReflectionExtensionPoint Reflection(this T instance)

    {

      return new ReflectionExtensionPoint { Instance = instance };

    }

 

    public static void SetProperty(

      this ReflectionExtensionPoint extensionPoint,

      string name,

      object value)

    {

      PropertyInfo propertyInfo = typeof(T).GetProperty(name);

      propertyInfo.SetValue(extensionPoint.Instance, value, null);

    }

 

    public static object GetProperty(

      this ReflectionExtensionPoint extensionPoint,

      string name)

    {

      PropertyInfo propertyInfo = typeof(T).GetProperty(name);

      return propertyInfo.GetValue(extensionPoint.Instance, null);

    }

  }

Of course, extending the generic ReflectionExtensionPoint class, we need to make our extension methods generic as well so that we can propagate the extended type.

By now, unit tests should turn green, and we should be looking for next bits of business value to provide.

powered by metaPost

Saturday, March 29, 2008 1:59:11 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
.net | .net - Extension Methods
# Friday, March 28, 2008

If you haven't read Part 1, Part 2 and Part 3 of this serie, go ahead, we'll wait right here.

In the previous post, we suggested that you can move instance methods that represent overloads to static extension methods.

It's been known for a while that static methods don't do well. They infer with most OO principles and are barely testable. Some will even define those as evil.

Selfishness

When you look at the definition of evil, it is used to indicate acts that are selfish.

Static Methods are selfish in the sense that they keep implementation details for themselves. They take control and keep it. They won't allow you to replace them with a mock version for test purposes. They won't allow their behaviour to be modified without digging into the inner guts and recompiling. They can't be decorated, they can't be proxied, they're selfish.

But can't we have both? The ease and greatness of extension methods without the selfishness and lack of testability of static methods?

Well yes you can... Sort of...

Let's start by looking at an extension method we previously developed:

public static class TypeExtensions

{

  public static bool Is<T>(this Type type)

  {

    return typeof(T).IsAssignableFrom(type);

  }

}

 

It contains almost no code but still, it can't be mocked nor replaced.

Make everything an instance again

In order to replace the implementation of this method with another one, we simply need to

1-Extract this method into an interface

public interface ITypeExtensions

{

  bool Is<T>(Type type);

}

2- Provide a default implementation.

public class DefaultTypeExtensions : ITypeExtensions

{

  public bool Is<T>(Type type)

  {

    return typeof(T).IsAssignableFrom(type);

  }

}

3- Make sure the extension method delegates to the instance method

public static class TypeExtensions

{

  public static ITypeExtensions Extensions = new DefaultTypeExtensions();

 

  public static bool Is<T>(this Type type)

  {

      return Extensions.Is<T>(type);

  }

}

Compromise

On the sunny side, we are now able to completely test our extension method implementation. It can also be mocked as we've extracted an interface. It can be replaced or decorated with a Thread-safe version.

On the dark side, you need to set your mock instance to the public static Extensions field in order for existing code to call the mock. It is sort of an indirect dependency.

Friday, March 28, 2008 1:57:28 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
.net | .net - Extension Methods

Part 1 and Part 2 of this serie presented the basics and design guidelines for developing great extension methods.

Today, we'll try to show how extension methods can be a great tool to lessen the burden of implementing any given interface.

As an example, let's take a look at Unity for a moment.

IUnityContainer is the main interface of Unity. It acts both as a registry of registered type mappings between an abstract type and a concrete type; and as a Service Locator (Dependency Lookup).

What we're used to

Here's a snippet of the RegisterType method with its different overloads:

 public interface IUnityContainer

{

    //...

    IUnityContainer RegisterType()

      where TTo : TFrom;

    IUnityContainer RegisterType(LifetimeManager lifetimeManager)

      where TTo : TFrom;

    IUnityContainer RegisterType(LifetimeManager lifetimeManager);

    IUnityContainer RegisterType(string name)

      where TTo : TFrom;

    IUnityContainer RegisterType(string name, LifetimeManager lifetimeManager)

      where TTo : TFrom;

    IUnityContainer RegisterType(string name, LifetimeManager lifetimeManager);

    IUnityContainer RegisterType(Type t, LifetimeManager lifetimeManager);

    IUnityContainer RegisterType(Type from, Type to);

    IUnityContainer RegisterType(Type t, string name, LifetimeManager lifetimeManager);

    IUnityContainer RegisterType(Type from, Type to, LifetimeManager lifetimeManager);

    IUnityContainer RegisterType(Type from, Type to, string name);

    IUnityContainer RegisterType(Type from, Type to,

      string name, LifetimeManager lifetimeManager);

}

12 different overloads!!! In total, there are 39 different methods on this interface.

Let's focus on the RegisterType method for a sec. What are the main differences between those overloads?

First and foremost, there's the Generic-strongly-typed version and the loosely-typed version. Then there's the name parameter that allows you to register the same type multiple times with different names. Then there's whether or now you want to specify a lifetimeManager.

If we were to implement that interface and all those RegisterType methods, what would happen? How would we do it? Well, we'd probably chain them all to a single one; the same we do it with chained constructors, right? Which one? The more specific one? Definitely:

 IUnityContainer RegisterType(Type from, Type to, string name, LifetimeManager lifetimeManager);

This is the core method. The one that rules them all. All other overloads are only there to ease usage; at the cost of putting a large burden on the developer. If we want to write an IUnityContainer decorator, we'd have 39 methods to implement... again... and out of those 39 methods, only 3 or 4 would have any valuable logic...

Interfaces on a diet

What if we slim down those interfaces. Let's pretend for one moment that we have a great job at Microsoft, working for the p&p team; and most of all, we get to design Unity! Woohoo!

Since we've been reading the Coach Factor (or are about to), we decide to slim down those pesky interfaces. What would it look like? Well, we already answered this one:

public interface IUnityContainer

{

    //...

    IUnityContainer RegisterType(Type from, Type to, string name, LifetimeManager lifetimeManager);

}

Oh yeah! We just removed 11 methods out of 39. But now what? Will we put the burden on the client of this interface to always call RegisterType with all 4 parameters? Nah...

 

Extension Methos as Overloads

What if we leveraged our knowledge of extension methods to ease usage of our new slimmed down interface? What would it look like? Exactly! It would exactly look like what we have in the default implementation of the IUnityContainer interface:

public static class UnityContainerExtensions

{

    public static IUnityContainer RegisterType(this IUnityContainer container)

        where TTo : TFrom

    {

        return RegisterType(container, null, null);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, LifetimeManager lifetimeManager)

        where TTo : TFrom

    {

        return RegisterType(container, null, null);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, LifetimeManager lifetimeManager)

    {

        return RegisterType(container, null, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, string name)

        where TTo : TFrom

    {

        return RegisterType(container, null, null);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, string name, LifetimeManager lifetimeManager)

        where TTo : TFrom

    {

        return container.RegisterType(typeof(TFrom), typeof(TTo), name, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, string name, LifetimeManager lifetimeManager)

    {

        return container.RegisterType(typeof(T), null, name, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, Type t, LifetimeManager lifetimeManager)

    {

        return RegisterType(container, t, null, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, Type from, Type to)

    {

        return RegisterType(container, from, to, null);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, Type t, string name, LifetimeManager lifetimeManager)

    {

        return container.RegisterType(t, null, name, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, Type from, Type to, LifetimeManager lifetimeManager)

    {

        return container.RegisterType(from, to, null, lifetimeManager);

    }

 

    public static IUnityContainer RegisterType(

      this IUnityContainer container, Type from, Type to, string name)

    {

        return container.RegisterType(from, to, name, null);

    }

}

Now what?

Well now we can use the full range of overloads and keep IUnityContainer interface as small as possible. It is going to make it a lot easier to mock, decorate and implement the interface without losing any capabilities or ease of use.

Also, we've shared the implementation of overloads throughout all implementations, mocks and decorators of IUnityContainer.

Be careful when designing and trimming down interfaces. It is important that there is no logic associated with the overloads; that is; if registering a component without a name would make a difference and wasn't the equivalent of calling RegisterType(null) then this technique isn't necessarily appropriate.

powered by metaPost

Friday, March 28, 2008 1:56:32 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
.net | .net - Extension Methods
# Wednesday, March 12, 2008

Part 1 presented a recap of extension methods. If you're not familiar with the concept, you should check it first.

Cohesion

The main concern with extension methods is that they aren't for everything; they have to be cohesive with the type being extended.

Let's say we add another extension method to the string class from the previous post:

  public static class StringExtensions

  {

    public static bool IsValidEmailAddress(this string instance)

    {

      if (instance.HasValue())

      {

        Regex expression = new Regex(

        @"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'

                *+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z             

                0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?");

 

        return expression.IsMatch(instance);

      }

      else

      {

        return false;

      }

    }

  }

Does this really make sense? Definitely not!

A string is not intended to contain "exclusively" email addresses; so you end up polluting your string class with domain-specific extensions.

  public class StringExtensionsFixture

  {

    [Fact]

    public void ConnectionString_Polluted()

    {

      string connectionString = "Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI;";

      Assert.False(connectionString.IsValidEmailAddress()); //Doesn't make sense!

    }

  }

Facade

Extension Methods should really be used to facade and simplify usage of existing scenarios without adding extra coupling on external concepts:

  public static class TypeExtensions

  {

    public static bool Is<T>(this Type type)

    {

      return typeof(T).IsAssignableFrom(type);

    }

  }

 

  public static class TypeExtensionsFixture

  {

    [Fact]

    public void Is()

    {

      // Without the extension, logic relies on the understanding of the obscure method "IsAssignableFrom".

      Assert.True(typeof(IComparable).IsAssignableFrom(typeof(int)));

 

      // With the extension, the developer leverages existing knowledge of the "is" operator

      Assert.True(typeof(int).Is<IComparable>());

    }

  }

One imporant thing to notice here is the usage of a "generic" extension method. We'll delve into more details about generic extension methods in a subsequent post.

However, some cross-cutting concerns such as Serialization, Conversion, Equality benefit largely from being published as extension methods instead of remaining in their own "helper" classes. The main reason for this is discoverability. Some people will argue that since the extension method isn't part of the extended type per se, it lowers discoverability.  "Helper" methods aren't any more discoverable.

Extension Point

Let's say we want to add the serialization "functionality" to any object, we could use extension methods and write something like:

  public static class SerializationExtension

  {

    public static void ToXml<T>(this T instance, string fileName)

    {

      XmlSerializer serializer = new XmlSerializer(typeof(T));

 

      FileStream stream = File.OpenWrite(fileName);

 

      using (stream)

      {

        serializer.Serialize(stream, instance);

      }

    }

 

    public static void ToBinary<T>(this T instance, string fileName)

    {

      BinaryFormatter formatter = new BinaryFormatter();

 

      FileStream stream = File.OpenWrite(fileName);

 

      using (stream)

      {

        formatter.Serialize(stream, instance);

      }

    }

  }

SerializationMessy

What's the problem here? We started polluting the "Person" type with non-related concerns such as Xml and Binary serialization. Just imagine one moment all the additional methods that could suddenly appear and pollute the Person object. It would lead to "Extension Method Hell".

One remedy is to try to group those methods into "Extension Points", grouping them by how related the concern is.

Introducing: the Extension Point object:

  public class SerializationExtensionPoint<T>

  {

    public T Value { get; set; }

  }

 

The goal of the extension point is to wrap an instance with a "typed scope", allowing the extension methods to be programmed against the extension point instead of the instance itself.

  public static class SerializationExtension

  {

    public static void ToXml<T>(this T instance, string fileName)

    {

      XmlSerializer serializer = new XmlSerializer(typeof(T));

 

      FileStream stream = File.OpenWrite(fileName);

 

      using (stream)

      {

        serializer.Serialize(stream, instance);

      }

    }

 

    public static void ToBinary<T>(this T instance, string fileName)

    {

      BinaryFormatter formatter = new BinaryFormatter();

 

      FileStream stream = File.OpenWrite(fileName);

 

      using (stream)

      {

        formatter.Serialize(stream, instance);

      }

    }

  }

We've added the Serialization() extension method that provides the typed scope. Other scopes could group non-functional extensions like Equality, Conversion and Comparison.

Serialization

In the image above, we can clearly see that the interface is a lot more cohesive and has only been polluted with a Serialization aspect.

The complete code would look something like:

  public class SerializationExtensionFixture

  {

    [Fact]

    public void ToXml()

    {

      Person person = new Person { FirstName = "John", LastName = "Doe" };

      person.Serialization().ToXml("john.xml");

    }

  }

 

In the next post, we'll try to explore in more details how we can benefit from generics in extension methods.

Wednesday, March 12, 2008 1:55:15 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
.net | .net - Extension Methods

Extension Methods is a cool new feature of .NET 3.5. It's syntactic sugar invented mainly for LINQ and allow the developer to get rid of most of the static "helper" methods.

If you haven't delved into them, here's a quick recap on how they're implemented using C# 3.0:

  public static class StringExtensions

  {

    public static bool HasValue(this string instance)

    {

      return !string.IsNullOrEmpty(instance);

    }

  }

Just remember there are three steps to define an extension method:

    • static class

    • static method

    • this modifier

      Once that done, you can use the method like any other instance method:

        public class StringExtensionsFixture

        {

          [Fact]

          public void HasValue_Null()

          {

            string text = null;

       

            Assert.False(text.HasValue());

       

            // What the compiler is calling behind the scenes

            Assert.False(StringExtensions.HasValue(text));

          }

      
      

      However, extension methods are different from regular instance methods as:

      • They support null references

      string text = null;

       

      // Will not throw a NullReferenceException

      Assert.False(text.HasValue());

      • They allow you to extend sealed classes by adding methods

      public sealed class String { ... }

      In an upcoming post, we'll show you how design considerations are really important when extending existing types.

      Wednesday, March 12, 2008 1:51:48 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
      .net | .net - Extension Methods
      # Tuesday, March 11, 2008

      nVentive will be presenting at the Ottawa Code Camp on April 5th. It's a free day, and a great opportunity to see what's happening in software development.

      Tuesday, March 11, 2008 8:32:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
      Announcement
      Search
      Archive
      <April 2008>
      SunMonTueWedThuFriSat
      303112345
      6789101112
      13141516171819
      20212223242526
      27282930123
      45678910
      Statistics
      Total Posts: 47
      This Year: 0
      This Month: 0
      This Week: 0
      Comments: 2
      Sign In