Using Extension Methods to Verify Assumptions

CraigBlog

Syndication

I was working on something with Tim yesterday, and between us we came up with what I think is a pretty cool trick. We were defining some extension methods on XElement and friends that make it easier to work work XHTML. Something like this:

doc.Html().Div(“foo”).Div(“bar”).Value

Which would pull out the text content of a div with a class of “bar” that was a descendant of a div with a class of “foo”. All well and good, but one of the problems we were trying to address is that we didn’t want to proceed if there was no div of class “foo”. A NullReferenceException would be thrown, but we wanted something more specific. So we came up with this:

public static T OrThrow<T>(this T obj, Exception e) {
    if (obj == null) {
        throw e; 
    } 
    return obj;
}

Which in turn allowed us to write this:

doc.Html().Div(“foo”).OrThrow(new MyException(“no foo”)).Div(“bar”).Value

The clever bit is that the OrThrow extension method is generic on the type it’s invoked on, and it returns that type, so you can insert it into a chained expression and you don’t lose any intellisense. And because of type inference, you don’t actually have to specify the type (you don’t have to type OrThrow<IEnumerable<XElement>>), which cleans up the expression a bit.

This approach is more general than just XHTML, of course. Really, it allows you to insert arbitrary assertions/checks into a series of chained calls using a fairly natural syntax (for some value of “natural”). Nothing you can’t do other ways, but we liked the way this came out enough to want to share it.


Posted Mar 18 2009, 09:02 AM by craig-andera

Comments

Wiz wrote re: Using Extension Methods to Verify Assumptions
on 03-18-2009 8:32 AM

Cool idea, thanks!

That Div() extension also looks very convenient to use.  Are you planning to publish and write about that when you're done, or is it something proprietary?

craig-andera wrote re: Using Extension Methods to Verify Assumptions
on 03-18-2009 8:43 AM

Unfortunately, it's not something I can really share, but the general idea is an extension method that looks like this:

public static IEnumerable<XElement> Div(this XElement parent, string class)

{

  return from div

  in parent.Elements("div")

  where div.HasAttribute("class") && div.Attribute("class").Value.Equals(class)

  select div;

}

I haven't compiled this, but you get the idea. Define something similar for body, span, and whatever other tags you want, and you're off and running. You'll probably also want one that's an extension of IEnumerable<XElement> but does basically the same thing.

Honestly, I'd be pretty surprised if someone hasn't already published something like this.

Rob Engberg wrote re: Using Extension Methods to Verify Assumptions
on 03-18-2009 3:32 PM

That is very cool!  I'll definitely be using that.   Though I'd probably just give it a string parameter for the exception message and build the exception inside the method (if necessary).  

Jason Haley wrote Interesting Finds: March 19, 2009
on 03-19-2009 8:31 AM
Freddy wrote re: Using Extension Methods to Verify Assumptions
on 03-20-2009 4:41 PM

Nice. It does allows you to provide extra info on what you want to validate. If you only needed to ignore the foo, I would go XPath instead :).

root.XPathSelectElement("./[class=@foo]/[class=@bar]")

Namespace: msdn.microsoft.com/.../bb156083.aspx

FromChina wrote re: Using Extension Methods to Verify Assumptions
on 04-01-2009 2:06 AM

I put codes belown in my common class

   public static T Instance(this T obj) where T:new()

   {

       if (obj == null)

       {

           obj = new T();

       }

       return obj;

   }

But i get the error "Constraints are not allowed on non-generic declarations"

Thanks for your reply:)

craig-andera wrote re: Using Extension Methods to Verify Assumptions
on 04-01-2009 5:03 AM

That should be

public static T Instance<T>(this T obj) where T: new()

The <T> indicates that the method is generic on T.

鬼话符 wrote 使用扩展方法对调用进行验证
on 04-02-2009 12:54 AM

利用C#3.0提供的扩展方法技术,可以为已经编译好的程序集类型增加新的方法,从而应对新的扩展。除了在可扩展性方面所具有的优势之外,如果能够合理地结合泛型与类型推断,扩展方法还可以有效降低代码的重复,...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?