Posts in category .net - page 17

Multiple-inheritance, composition and single responsibility principle in .NET

.NET is often chided by C++ developers for failing to support multiple-inheritance. The reply is often Favor object composition over class inheritance – a mantra chanted from everywhere including the opening chapters of the Gang of Four’s Design Patterns book.

If the accepted mantra is that your object should expose interfaces and delegate the implementation of those interfaces elsewhere then it could really do with some better support than .NET currently offers especially where the interface comprises more than a member or two.

Consider the following fragment of a class for customer price-lists (properties and methods omitted). We decide to support IList so that consumers of our class can add, remove and iterate over the prices in a familiar manner (principle of least surprise).

public class CustomerPriceList : IList<ProductPrice> {
    private List<ProductPrice> productPrices = new List<ProductPrice>();
    public Customer Customer;
}

Implement interface

Visual Studio offers some assistance where you can choose Implement interface _IList_ which gives you all the method definitions with the very unhelpful body of throwing an exception of “This method or operation is not implemented”. It requires some work to fill in all these definitions to something that works:

public class CustomerPriceList : IList<ProductPrice> {
    private  List<ProductPrice> productPrices = new  List<ProductPrice>();
    public  Customer Customer;

    public int IndexOf(ProductPrice item) {
        return productPrices.IndexOf(item);
    }

    public void Insert(int index, ProductPrice item) {
        productPrices.Insert(index, item);
    }

    public void RemoveAt(int index) {
        productPrices.RemoveAt(index);
    }

    public ProductPrice this[int index] {
        get { return productPrices[index]; }
        set { productPrices[index] = value; }
    }

    public void Add(ProductPrice item) {
        productPrices.Add(item);
    }

    public void Clear() {
        productPrices.Clear();
    }

    public bool Contains(ProductPrice item) {
        return productPrices.Contains(item);
    }

    public void CopyTo(ProductPrice[] array, int arrayIndex) {
        productPrices.CopyTo(array, arrayIndex);
    }

    public int Count { get { return productPrices.Count; } }

    public bool IsReadOnly { get { return ((IList)productPrices).IsReadOnly; } }

    public bool Remove(ProductPrice item) {
        return productPrices.Remove(item);
    }

    public IEnumerator<ProductPrice> GetEnumerator() {
        return productPrices.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return ((IEnumerable) productPrices).GetEnumerator();
    }
}

This is a lot of effort for a cluttered solution.

Use inheritance to subclass List

public class CustomerPriceList : List<ProductPrice> {
  public Customer Customer;
}

Small amount of code but not an option if you have a class hierarchy in place or need to implement multiple interfaces.

Expose IList property directly

public class CustomerPriceList : IListable<ProductPrice> {
  private List<ProductPrice> productPrices = new List<ProductPrice>();
  public Customer Customer;
  public IList<ProductPrice> ProductPrices { get { return productPrices; } }
}

This works but means CustomerPriceList can not control any of the IList implementation such as validation.

Methods may also start accepting IList instead of CustomerPriceList because developers imagine the parts to be more decoupled than they actually are and are encouraged to code to interfaces not concrete classes.

Refactoring away from this at a later date would require a IList wrapper than delegated calls back to the containing class to prevent an interface-breaking change.

Introduce interface to declare IList available

Add an interface that signifies a IList can be obtained by calling the named method, e.g.

public interface IListable<T> {
  IList<T> GetList();
}

This is a similar pattern to that of IEnumerable and IEnumerator whereby one interface signifies the availability of the other. In this example our class would look like:

public class CustomerPriceList : IListable<ProductPrice> {
  private List<ProductPrice> productPrices = new List<ProductPrice>();
  public Customer Customer;
  public IList<ProductPrice> GetList() {
    return productPrices;
  }
}

Which is less code, a closer adherence to single responsibility principle (SRP) and the ability to change without breaking the interface although it still does nothing to prevent passing IList or IListable interfaces where CustomerPriceList would be more suitable. An IPriceList class could be introduced although it starts to feel like abstract infinity.

Improved support from .NET

I’d really like to see .NET improve on the support for interfaces and composition, like perhaps the following:

public class CustomerPriceList : IList<ProductPrice> goto productPrice {
  private IList<ProductPrice> productPrice = new IList<ProductPrice>();
  public Customer Customer;
}

This would signify to the compiler that all IList interfaces should be wired up to the productPrice variable unless explicitly defined and gives goto a whole new lease of life ;-)

[)amien

Typed session data in ASP.NET made easier still

Philippe Leybaert is unimpressed with Microsoft’s Web Client Software Factory approach for typed session data and offers his own Typed session data made (very) easy which still seems overkill to me comprising as it does of generics, a delegate a helper class to achieve the desired effect. (Whilst you are there check out his very interesting MVC project for ASP.NET called ProMesh)

The solution which I have been using since my .NET 1.1 days is much simpler still and involves nothing more than creating a plain class with properties for every session variable and a static get accessor that obtains or creates it on the HttpContext similar to a singleton.

Here’s an example with the important Current property (slightly cleaned up and improved for this post ;-)

public class MySession {
  public string Name;
  public int LoginID;
  public int CustomerID;

  public static MySession Current {
    get {
      MySession currentSession = HttpContext.Current.Session["_session"] as MySession;
      if (currentSession == null) {
        currentSession = new MySession();
        HttpContext.Current.Session["_session"] = currentSession;
      }
      return currentSession;
    }
  }
}

Using the session data then simply involves operations like:

MySession.Current.Name = NameTextBox.Text;
NameLabel.Text = MySession.Current.Name;

This solution is a lot clearer however all of these solutions use HttpContext.Session which is actually supposed to be there for compatibility with ASP.

Ideally Microsoft would provide us with an option in web.config whereby we can choose our session class and it would just instantiate and track it as part of the session life-cycle.

[)amien

Partial methods in .NET 3.5, overview and evolution

One of the interesting new things in .NET 3.5 is partial methods which are now being used extensively by LINQ to SQL and no-doubt will be Microsoft’s corner-post of extensibility for generated classes. Here’s a quick overview:

Extending generated code via inheritance (.NET 1.1)

When inheriting from generated classed designers often provide virtual methods for you to override and extend at a cost of being forced to inherit from the generated class instead of one of your own choosing. e.g.

class Customer {
    private string name;
    public string Name {
        set {
            name = value;
            OnNameChanged();
        }
    }
    protected virtual void OnNameChanged() {
    }
}

class Customer : CustomerGenerated {
    protected override void OnNameChanged() {
        DoSomething();
    }
}

Extending generated code via delegates/event handlers (.NET 2.0)

.NET 2.0 introduced partial classes and code generation moved into separate files that were pulled together at compile-time to provide a single consistent class leaving you free to choose your own inheritance.

The drawback is that you can not override generated methods because they are not inherited but rather merged at compile-time.

This means if you want to provide extensibility in your generated code you will either need to use inheritance or generate delegates/events that consumers of your class can hook up. This works but is not intuitive as demonstrated:

partial class Customer {
  protected event EventHandler NameChangedHandler;
  private string name;
  public string Name {
    set {
      name = value;
      if (NameChangedHandler != null)
          NameChangedHandler.Invoke(this, null);
    }
  }
}

partial class Customer {
  public Customer() {
    NameChangedHandler += OnNameChanged;
  }

  protected void OnNameChanged(object sender, EventArgs e) {
    DoSomething();
  }
}

Extending generated code via partial methods (.NET 3.5)

.NET 3.5 sees Microsoft answer the problem by allowing the partial keyword to be used at method level instead of just at class level:

partial class Customer {
  private string name;
  public string Name {
    set {
      name = value;
      OnNameChanged();
    }
  }
  partial void OnNameChanged();
}

partial class Customer {
  partial void OnNameChanged() {
    DoSomething();
  }
}

Thoughts

This is clearer than using delegates & events but still suffers some limitations:

  • Only one method can have a body so you can’t override generated code
  • Properties are not supported

If .NET supported multiple inheritance then partial classes and methods would be redundant. As Microsoft tout interfaces and composition as a better approach it is about time they added support to automatically wire up an interface to a compound object (a blog post for another time).

[)amien

Rails-style controllers for ASP.NET

Rob Conery has been putting together some great screen casts on SubSonic and his latest on generating controllers pointed out that ASP.NET doesn’t support the Rails-style http://site//controller/method style of execution.

This got me quite excited and I’ve put together a proof-of-concept web project that demonstrates mapping the path to controller methods using an IHttpHandler and reflection.

How it works

It registers the ControllerHttpHandler via the web.config:

<httpHandlers>
  <add path="/ctl/\*/\*" verb="POST,GET,HEAD" type="ControllerHttpHandler" />
</httpHandlers>

There is a very basic Controller abstract base class that just provides a simple way of accessing the context for dealing with request/response for now.

public abstract class Controller
{
  protected System.Web.HttpContext context;

  internal Controller(System.Web.HttpContext context) {
    this.context = context;
  }
}

We then have a test controller or two that implement from this with a couple of methods and the required constructor:

public class TestController : Controller
{
  public TestController(System.Web.HttpContext context) : base(context) { }

  public void Index() {
    context.Response.Write("This is the index");
  }

  public void Welcome() {
    context.Response.Write("Welcome to the TestController");
  }
}

Finally the magic that joins them up is the ControllerHttpHandler:

using System;
using System.Web;
using System.Reflection;

public class ControllerHttpHandler : IHttpHandler
{
  public void ProcessRequest(HttpContext context) {
    string[] parts = context.Request.Path.Split('/');
    if (parts.Length < 4) {
      context.Response.Write("No controller & member specified");
      return;
    }

    string controllerName = parts[2];
    string methodName = parts[3];
    Type potentialController = Type.GetType(controllerName);
    if (potentialController != null && potentialController.IsClass && potentialController.IsSubclassOf(typeof(Controller))) {
      MethodInfo potentialMethod = potentialController.GetMethod(methodName);
      if (potentialMethod != null) {
        Controller controller = (Controller) Activator.CreateInstance(potentialController, context);
        potentialMethod.Invoke(controller, null);
      }
      else
        context.Response.Write(String.Format("Method '{0}' not found on controller '{1}'", methodName, controllerName));
    }
    else
      context.Response.Write(String.Format("Controller '{0}' not found", controllerName));
  }

  public bool IsReusable {
    get { return false; }
  }
}

That’s it!

Limitations

The controllers and methods are mapped at run-time using reflection. This would probably be too slow for production. Also it currently has to be in a top-level folder because I can’t figure out how to pass the HTTP request back to ASP.NET to try with the rest of the stack if we don’t have a matching controller/method.

One option might be to have no httpHandlers in the web.config and add the exact controller/method maps at build or run-time. This solves both the top-level problem and potentially the speed.

Another option to address just the speed of reflection would be to cache the path/method strings to the actual method and type so the only reflection would be the Activator.CreateInstance. If that is slow then we could look at pooling the controller instances themselves.

Going forward

Parameters for a method could be extracted and parsed from the query-string – they are currently ignored.

Response is raw output – we could do something very similar to rhtml.

I’m going to chat things over with the Subsonic team and see if we can come up with anything from here.

[)amien