DCSIMG
October 2008 - Posts - .NET Geek

.NET Geek

"It is upon the Trunk that a gentleman works" - Confucius

October 2008 - Posts

The C# team engages in the battle - C# vs VB.NET

I’m not going to say a word about which is better. Why? Because in the scope of things it doesn’t matter. But you have to wonder if the right hand knows what the left hand is doing inside Microsoft. (One hand being the C# team the other the VB.Net team – you can choose)
I got up early this morning to watch the recording of Anders Heijlsberg’s presentation at the PDC on the future of C#. 14 minutes into the recording I had to stop because the kids were up. I’ll watch the rest tonight, but an impression stuck with me.

At about 13 minutes into the recording, Anders shows an image of two kids hugging. The co-existence of C# and VB.Net. He tries to drive home the point that they are both good with some divergence in features blah blah blah…

I can understand that when two separate groups develop two separate languages there’s an individual touch on the implementation. What’s important to one team is not as important to the other. But when one group goes off on a joint venture with a third party tool company that doesn’t provide an addition to the language of the group, but to the developers ability to be efficient in the IDE I’m left wondering if anyone is in charge on a level above the syntax. For those wondering, the tool is CodeRush Xpress which will be available for free for C# developers.

kick it on DotNetKicks.com

CodeRush for free! CodeRush Xpress for Visual Studio announced

Fresh from the DevExpress booth at PDC comes an announcement that DevExpress will be providing a significant subset of CodeRush and Refactor! Pro for free. You can see the announcement here and Mark Miller gives a more technical overview of what’s available. You can download it from the DevExpress site now.

It’s not all rosy though. The Xpress version is C# only! Go figure? I was very surprised by this since CodeRush and Refactor work with both VB.NET and C# seamlessly. Did they announce the end of VB.Net at PDC?
Another limitation is that CodeRush Xpress edition is not supported in the Express editions of Visual Studio.

Happy Coding…

 

kick it on DotNetKicks.com

CodeRush Plugin – Navigate to Implementation Part 3

In this part we’ll look at the Implementors class. As we described in part 1, a the Navigation Provider will call into our plugin twice. Once to give us the chance to make our plugin available to the user and a second time if the user selected one of our menu items. When the Navigation provider raises the event CheckAvailability we need to do two things.

  1. Check if this plugin is available in the current context.
  2. Alter the menu displayed so our options are available to the user.

In step one we will first check if we are positioned on a method call who’s declaring type is an interface. If we are we need to find all classes that implement that interface and add them to the menu. Here’s the code:

internal class Implementors : IEnumerable<Class>, IEnumerable

{

    private List<Class> _implementors;

    public Implementors()

    {

        _implementors = new List<Class>();

    }

    public void Load(LanguageElement element)

    {

        Reset();

        if (!OnCall(element))

            return;

        IElement declaringType = element.GetDeclaration().Parent;

        Interface abstraction = declaringType as Interface;

        if (abstraction == null)

            return;

        LoadImplementors(abstraction);

    }

    public int Count

    {

        get { return _implementors.Count; }

    }

    private void Reset()

    {

        _implementors.Clear();

    }

    private static bool OnCall(LanguageElement element)

    {

        return (element is MethodReferenceExpression);

    }

    private void LoadImplementors(Interface abstraction)

    {

        ITypeElement[] decendants = abstraction.GetDescendants();

        foreach (ITypeElement implementor in decendants)

        {

            Class implementingClass = implementor.GetDeclaration() as Class;

            if (implementingClass != null)

            {

                _implementors.Add(implementingClass);

            }

        }

    }

    public IEnumerator<Class> GetEnumerator()

    {

        foreach (var item in _implementors)

        {

            yield return item;

        }

    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    {

        return GetEnumerator();

    }

}

Let’s have a look at the Load method. We first need to clear any classes that were found from previous invocations of the plugin. Since this code in our plugin is always run as the result of a user request, we don’t have to be to hung up on optimizations. It would be much different if we needed to paint on the screen or do some other performance critical operations
Next we check if the caret is currently located on a method call.

private static bool OnCall(LanguageElement element)

{

    return (element is MethodReferenceExpression);

}

Ok, so how did I know what to check for? CodeRush ships with a niftly tool that will display the parsed source tree as it looks to CodeRush.

image

The Source Tree viewer is extremely useful!

Checking the context

Next we check if the method is invoked on an Interface declaration.

IElement declaringType = element.GetDeclaration().Parent;

Interface abstraction = declaringType as Interface;

if (abstraction == null)

    return;

So if we are located on a method that is called on an interface, we can look for descendants of this Interface. (I actually think of them as implementors. Maybe I should stick with the CodeRush terminology as that is the ubiquitous language of CodeRush plugins.

Loading the implementors

private void LoadImplementors(Interface abstraction)

{

    ITypeElement[] decendants = abstraction.GetDescendants();

    foreach (ITypeElement implementor in decendants)

    {

        Class implementingClass = implementor.GetDeclaration() as Class;

        if (implementingClass != null)

        {

            _implementors.Add(implementingClass);

        }

    }

}

One issue I had is that much of the data is exposed as methods and not as properties. The implication of that is that you can’t expand them in the visualizers in Visual Studio. Am I missing something?

So how do you find your way through the CodeRush object model?

NDepend DependencyGraph Snapshot

(DevExpress.CodeRush.StructuralParser)

First of all, CodeRush ships with a decent number of plugin source code. That is usually the first place I look. The Source Tree explorer is indispensable. The documentation is not extensive enough to be of much help, but hopefully that will change. As I mentioned in an earlier post, Mark Miller is doing online tutorials which are very good and there’s also a session on DnrTV which is good. DevExpress is hosting an online discussion forum for asking questions related to their products. Note that this is a peer2peer (customers helping customers) forum. Despite that, DevExpress developers are monitoring the forums and they jump in with assistance.

An online community forming?
A few developers that are developing plugins for CodeRush have started an open source project DxCoreCommunityPlugins that aggregates plugins. Looks promising. The project has some good initiatives despite the fact that some of the plugins seem to have matching functionality in CodeRush. (Probably developed after the plugin was released)

That concludes this part. In the next and last part I’ll walk through some of the code in the Navigator class.

 

 

 

 

 

Share this post : del.icio.us it! digg it! dotnetkicks it!

CodeRush Plugin - Navigate to Implementation Part 2

In the previous post we just defined what we want the plugin to do. Let's start to walk through the process of creating a plugin with CodeRush.

There's some plumbing that needs to be done every time you create a plugin and that is not directly related to the functionality of the plugin. For this part I'll just point you to a plugin tutorial by Mark Miller. Since our plugin will handle navigation it seems natural to hook into the Navigation provider system provided by CodeRush.

  1. Open the plugin designer
  2. The NavigationProvider does not show up in the toolbox by default so we need to add it.
  3. Place a NavigationProvider on the designer and subscribe to the CheckAvailability and Navigate events.

Here's a dump of all of the code in the code-behind of the plugin.

namespace CR_NavigationContrib

{

    public partial class NavigationContribPlugIn : StandardPlugIn

    {

        private Implementors _implementors;

        // DXCore-generated code...

        #region InitializePlugIn

        public override void InitializePlugIn()

        {

            base.InitializePlugIn();

            _implementors = new Implementors();

            //

            // TODO: Add your initialization code here.

            //

        }

        #endregion

        #region FinalizePlugIn

        public override void FinalizePlugIn()

        {

            //

            // TODO: Add your finalization code here.

            //

            base.FinalizePlugIn();

        }

        #endregion

        private void navigationProvider1_CheckAvailability(object sender, CheckContentAvailabilityEventArgs ea)

        {

            _implementors.Load(ea.Element);

            ea.Available = _implementors.Count > 0;

            if (!ea.Available)

                return;

            foreach (var item in _implementors)

            {

                ea.AddSubMenuItem(item.FullName, item.Name);

            }

        }

        private void navigationProvider1_Navigate(object sender, NavigationEventArgs ea)

        {

            SubMenuItem selectedMenu = ea.SelectedSubMenuItem;

            if (selectedMenu == null)

                return;

            Class implementor = _implementors.Where(c => c.FullName == selectedMenu.Name).FirstOrDefault();

            if (implementor != null)

            {

                Navigator navigator = new Navigator(implementor, ea.Element);

                navigator.Navigate();

            }

        }

    }

}

What we see in the code above, are two methods InitializePlugin() and FinalizePlugin() which are standard boilerplate with every plugin and two event handlers navigationProvider1_CheckAvailability and navigationProvider1_Navigate for the navigation provider. In addition to the plugin class, the plugin has two additional classes that we write. Implementors and Navigator. The Implementors class is responsible for storing which classes implement the Interface we're on if any. The Navigator class will take us to the implementation when the navigation method is called.

A few more issues that are worth to mention.

Here's a screenshot of the event arguments for the CheckAvailability event. As you can see there's quite a lot going on. This turns out to be both a blessing and a curse. On the blessing side you can achieve pretty much everything you want. On the curse side, it is not easy to find what you want.

I wonder why the CodeRush team created such a flat object model. I would much rather prefer a deeper, but more categorized hierarchy. I'm not complaining, don't get me wrong, but the current object model without documentation is not easy to navigate (for me, that is). Maybe if I had a lot of experience with VS extensibility much of what I struggle with would be moot. Time will tell.

image

In the CheckAvailability event handler we get a list of classes that implement the interface we're on. If the Implementors class found at least one class that implements the Interface, we tell CodeRush that our navigation provider should be available to the user. In addition we populate the navigation menu with sub menu items, one for each class. We use the fully qualified name of the class as the key for the menu.

private void navigationProvider1_CheckAvailability(object sender, CheckContentAvailabilityEventArgs ea)

{

    _implementors.Load(ea.Element);

    ea.Available = _implementors.Count > 0;

    if (!ea.Available)

        return;

    foreach (var item in _implementors)

    {

        ea.AddSubMenuItem(item.FullName, item.Name);

    }

}

The Navigate event handler will be called if the user selected one of the sub menu items we created in the CheckAvailability handler. Here we check that we got a menu (maybe not necessary since we couldn't get here without clicking one). Next we query the Implementors class for a class that matches the key we stored as the menu name earlier. If we find a class that implements the interface, we instantiate a new Navigator that will handle the navigation to the location of the implementation. (eg. open and activate files etc.)

private void navigationProvider1_Navigate(object sender, NavigationEventArgs ea)

{

    SubMenuItem selectedMenu = ea.SelectedSubMenuItem;

    if (selectedMenu == null)

        return;

    Class implementor = _implementors.Where(c => c.FullName == selectedMenu.Name).FirstOrDefault();

    if (implementor != null)

    {

        Navigator navigator = new Navigator(implementor, ea.Element);

        navigator.Navigate();

    }

}

In the next part we'll walk through the Implementors and Navigator classes. (At least one of them)

Share this post : del.icio.us it! digg it! dotnetkicks it!

CodeRush Plugin - Navigate to Implementation Part 1

In a post last week I mentioned a shortcoming of CodeRush navigation capabilities. On Friday (we don't work Fridays here) I decided that instead of sitting on my hands and complain I'll try to do something about it. I'll write a plugin for CodeRush that does this. I've written a few CodeRush plugins before, but I have never found the time to make something that I feel I can share with others. Not that the current implementation is a master piece, but it is small simple and works for what I want it to.

Because in my opinion it is such a pain to navigate the CodeRush object model I'll document here what I did and maybe the following will happen:

  • Someone will comment on the code suggesting a better way of achieving the same result.
  • Someone will use the code to implement his/her own plugin.

So here we go.

The first step is to define what we want to achieve. Take the following code.

public class CarTester

{

    ICar _car;

    public CarTester(ICar car)

    {

        _car = car;

    }

 

    public void TestCar()

    {

        _car.Drive();

        _car.PushBreaks(2);

    }

}

 

Let's imagine that there are many implementations of ICar such as Sedan, Trailer etc.

You are interested in working on the Truck Implementation. While getting familiar with the code you end up in the TestCar() method in CarTester. At this point you want to jump to the Truck implementation of ICar. So what do you do in Visual Studio to get to the Truck implementation? F12? It will only take you to the interface. You're out of luck. The goal of the plugin is to: "Position the caret on a method that's called on an Interface such as _car.Drive() and navigate to an implementation of your choice".

In the screenshot below you can see that the menu shows a list of all classes that implements the Interface ICar.

 

 

jump feature menu

 

 

In the next part we will start to walk through the code of the plugin.

 

kick it on DotNetKicks.com

From CodeRush to Resharper and Back...

I've been using CodeRush together with Refactor! Pro from DevExpress for over a year. A few weeks back I made a decision to leave my comfort zone and use Resharper from JetBrains for a few weeks .

Why?

  • It's only when you're uncomfortable you really learn.
  • I wanted to get a better feeling what some of my friends in the Alt.Net community is raving about when they talk about Resharper. (It is my perception that among Alt.Netters Resharper has a stronger foothold.)
  • My CodeRush subscription (which comes bundled with Refactor! Pro) was about to expire. (99$ to renew)
  • A need for change...

To be fair, I consider myself a CodeRush power user and I have invested significant amounts of time learning it. I am biased towards preferring CodeRush even if only in the sense that I don't want to loose my own investement. CodeRush comes bundled with Refactor! Pro, so whenever I write CodeRush it implies Refactor! Pro as well.

I'm not going to make this an exhaustive comparison, but rather try to point out the major areas of concern in my case. The bottom line is that both tools are excellent.
Note: It's beyond me how someone can write code without the support that is given from tools like these.

Here's what I did 3 weeks ago:

  • Uninstalled CodeRush and Refactor! Pro (v 3.0.8)
  • Downloaded and installed ReSharper (v 4.1)
  • Downloaded the keyboard map for ReSharper.
  • Read through 31 days of ReSharper by Joe White.
  • I started to watch the tutorial videos on the JetBrains site, but I found them annoying.

I did the above in a couple of hours during  an evening at home. I also remapped some of the key mappings to match those of CodeRush so make the transition easier. After a few hours of coding (with the keyboard map close), my biggest surprise was that I didn't slow down as much as I expected.
I managed to stay with ReSharper for the 14 day trial period, but then unistalled it and reinstalled CodeRush. Here are the main comparisons that I made.

Navigation
The ReSharper navigation is just better than that of CodeRush. For example, the following code is common in our system.

ISomeInterface someInterfaceImpl;
someInterfaceImpl.DoSomething();

There are many classes that implement ISomeInterface and I often will position the caret on DoSomething() where the next action is to navigate to the implementation that I'm currently interested in. ReSharper prompts me with a list of implementations and I just select one and it takes me there.

+1 for ReSharper.

Refactoring
Both tools have very strong refactoring support. Refactor! Pro has many more refactorings, but the essentials are covered by ReSharper as well. (For me the line between CodeRush and Refactor! Pro is somewhat blurred)

+1 for Refactor! Pro

Code Issues
ReSharper's static code analysis is more mature than that of CodeRush. In the current daily builds of CodeRush there are too many false positives to make the feature very useful. DevExpress is however releasing a new version of CodeRush with static code analysis in the near future. I especially liked the feature in ReSharper that let me turn off CodeAnalysis for a specific file. (Excellent for designer generated files)

+1 for ReSharper

Templates
The CodeRush template engine is so much better than that of ReSharper that you can't compare between them. Any comparison will do CodeRush injustice. It should be noted that it takes time to learn the CodeRush templates, but once you do you will not give it up.

This is a deal breaker for me.
+5 for CodeRush

Discoverability
Both tools come with a significant learning curve. The CodeRush training window is indispensable when learning the template shortcuts. Other than that, you need to memorize shortcuts. DevExpress has started a video channel on their web site with lots of good tutorials.

+1 CodeRush

Intellisense
ReSharper replaces the built in intellisense with its own. It is better than that of Visual Studio. It took me some time to get used to, but I liked it. I'll miss it! The template engine compensates somewhat for this.

+1 ReSharper

User Interaction
For all of those who whine about all the arrows and UI fireworks in CodeRush, let me just state that I don't use any of it. I have them all turned off.
With that out of the way, the CodeRush UI much better than that of ReSharper. Not only in the way it looks, but in the way that it lets you work in a more fluid way. No dialogs or wizards. The preview of changes to your code before a refactoring is stunning. Stunning as in beautiful, but also very useful.

+1 CodeRush

Performance
I didn't notice any performance problems with either. Machine spec: DELL M1730 Core2 x9000 at 3.0Ghz, 4GBRam, 2x200GB Raid0 HDD.

Misc
While I found the ReSharper unit test support very nice, it didn't add much to what I already use. CodeRush doesn't have a unit test tool.

A note about the future
CodeRush and ReSharper become more and more similar with every release. IMHO, the company that manages to get the community to invest in plugins for its tool will be the winner of this battle. On this account both companies are losers as of now. While they have great extensibility support, it's a dark art of those with too much time. I don't have any experience with developing plugins for ReSharper, but I saw a few complaints on blogs about lacking documentation and samples. The CodeRush plugin API is also mostly undocumented. Mark Miller of DevExpress has two excellent plugin tutorials, but developers need solid API documentation for plugin development to take off. I have several plugins in the drawer actually, but not enough time to dig through undocumented APIs to cover edge cases that don't appear in the samples that ship with the product.

Conclusion
As I stated earlier, both tools are very good, but CodeRush with Refactor! Pro let me develop with less friction.

Happy Coding...

Share this post : del.icio.us it! digg it! dotnetkicks it!