DCSIMG
June 2008 - Posts - IronShay

June 2008 - Posts

Using "using" with a method

This is a coding technique I've learned today from looking at Rhino mocks Playback() method code.
It's a nice and smooth technique and I can think of several uses for it.

Consider the following code:

public static void DoSomething()

{

    TimerClass timer = new TimerClass();

 

    using (timer.CountTime())

    {

        string s = "hello world";

        for (int i = 0; i < 100000; i++)

        {

            int index = s.IndexOf("world");

        }

    }

}

This code will result in writing to the console: "Total time: 110ms".
How is it done?

public class TimerClass

{

    public IDisposable CountTime()

    {

        return new MyTimer();

    }

 

    private class MyTimer : IDisposable

    {

        int start;

 

        public MyTimer()

        {

            start = Environment.TickCount;

        }

 

        public void Dispose()

        {

            Console.WriteLine("Total ms: {0} ms", (Environment.TickCount - start));

        }

    }

}

The "secret" is returning an inner disposable class that will take care of what you need...

Hope you've been enlightened,
Shay.

Share this post : del.icio.us it! digg it! dotnetkicks it! technorati!
Posted by shayf | 4 comment(s)

Jumping on the Environment Trend

Recently everyone has been obsessed with the environment (at least the politicians...) and even I have started recycling and print double sided... But did you know that the .Net framework had tuned to the recent trends as well?

Save the trees!

So today we're going to talk about the System.Environment class and introduce some time-saving methods provided by it.

Useful information

The Environment class holds some valuable information about the application's environment (surprise surprise!). It exposes properties such as MachineName, OSVersion, UserDomainName, UserName, CurrentDirectory and the very helpful StackTrace property.
When you're debugging, this can be a lifesaver. You can log all the calls to a single method and find out who's calling it and when, just write out the Environment.StackTrace value.
For example, the following code:

class Program

{

    static void Main(string[] args)

    {

        Go();

    }

 

    public static void Go()

    {

        Console.WriteLine(Environment.StackTrace);

    }

}

 

Results in:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at TheEnvironmentTrend.Program.Go() in c:\Demo\Program.cs:line 18
at TheEnvironmentTrend.Program.Main(String[] args) in c:\Demo\Program.cs:line 13
Press any key to continue . . .

 

Special folders

Sometimes you need the path to some OS special folders. Getting them yourself might be a bit tricky, so instead, the Environment class comes to our aid:

public string GetTheUsersDesktopPath()

{

    string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

 

    return path;

}

 

The GetFolderPath method returns the path to the given special folder. The SpecialFolder enum includes ApplicationData, InternetCache, History, MyDocuments, MyPictures and more.

Environment variables

Let's say your application stores data in the AppData folder. You can't assume that the AppData folder exists on the user's C drive, so you need to get the AppData path first. You could do it using the GetSpecialFolder method, but there is a better way:

public string GetMyAppDataPath()

{

    string path = Environment.ExpandEnvironmentVariables(@"%appdata%\MyApplication\Something");

 

    return path;

}

 

The ExpandEnvironmentVariables method is a huge time saver. You can set there any environment variable you want and they will be translated to their real values (like: logonserver, computername, homedrive and more. Try Start->Run->cmd, type "set" and run. You'll see your environment variables there). This doesn't have to be used just for paths, you can use it for various purposes. For instance, consider the following string: "You are %username%, you have installed windows on %windir% and you have a %NUMBER_OF_PROCESSORS% processor computer". This would be a great welcome message! (hmmmm)

The method Al-Gore would've liked

Environment.FailFast
Except from the fact that this is what we've been doing during the last centuries, this can be helpful in your code sometimes. For example, when you have an exception and you know that your application won't rise again from it, you can shut down the application, with no finally blocks called. Pay attention that calling this method will brutally shut down your application, so use it wisely.
For example, the following code:

public void ByeBye()

{

    try

    {

        Console.WriteLine("Doing something important");

 

        throw new Exception("Oh no!");

    }

    catch

    {

        // Our environment is at the no-return point!

        Environment.FailFast("No real explanation for the kids");

    }

    finally

    {

        Console.WriteLine("We're gonna save it now!");
        FixTheEnvironment();

}

}

Will result in:

Doing something important
Press any key to continue . . .

= deadTree

The finally block wasn't called...

Keep the environment safe!
Shay

Share this post : del.icio.us it! digg it! dotnetkicks it! technorati!
Posted by shayf | 1 comment(s)

When The Whole is Greater Than The Sum of Its Parts

I did a lecture earlier this week about the design behind VSTO 3.0 Ribbon. This is the follow-up post with detailed information and a complete demo.

Presentation: download
Demo project: download
In order to run the demo, open it in VS2008, build the setup project and install it, then run Word 2007.

How to extend the Office 2007 Ribbon?

In order to define a custom ribbon, you should construct an xml file that describes the controls you want to present there.
For example, a ribbon xml file can be like the following:

<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">

    <ribbon>

        <tabs>

            <tab idMso="TabAddIns">

                <group id="group1" label="group1">

                    <button id="myButton" onAction="myButton_Click" getLabel="GetLabel" showImage="false" />

                </group>

            </tab>

        </tabs>

    </ribbon>

</customUI>

This configures a single ribbon, tab, group and a button. You can also see here some bold text, which emphasizes the callback method names that one can define on this configuration file.

The next step is to create an Office add-in, this can be a VSTO add-in, shared add-in or any other add-in that will work. For example, in order to create a Shared Add-in project, Open VS, click on File->New->Project. Then go to "Other project types"->Extensibility and choose "Shared Add-in". A quick wizard will guide till you can start writing your add-in code.
Now, all our add-in needs to do, is to implement IRibbonExtensibility and return the xml we've mentioned above. For instance:

#region IRibbonExtensibility Members

 

public string GetCustomUI(string ribbonID)

{

    return GetResourceText("Ribbon.xml");

}

 

#endregion

Here I assume that the xml file is stored in a resource named "Ribbon.xml" and that I have a method named "GetResourceText" that returns the file contents.

When Office loads the add-in, it calls the callbacks that was defined on the xml using reflection. This is an important part for the next parts of this article.
Sample implementation can be:

public string GetLabel(IRibbonControl control)

{

    return "Click Me!";

}

Refreshing the ribbon is done by calling the ribbon's Invalidate and InvalidateControl methods.

Take a look at the presentation, where you can see the flow between Office and the Add-in.

What Happened on VSTO 3.0?

If you second look on the last part, or worst - if you try to develop applications that way, you'll figure out pretty quickly that this is not our winning horse. You need to master xml files, various interfaces and you need to design the UI without seeing it until you execute your add-in for the first time.

VSTO 3.0 for Visual Studio 2008 took all of that into consideration - you don't have to worry about xml anymore, you don't have to implement interfaces and you even have a full designer support.

Key Concepts of VSTO 3.0 Ribbon

Just to make clear - no changes were made to Office before and after VSTO 3.0. Nothing was added in order to support it. VSTO 3.0 wraps the xml, callbacks and interfaces with developer-friendly classes and adds a full designer support.
This is a great thing, and it's even better if you think that it uses current abilities in order to take them to the next level - sound like we're experiencing the evolution right before our eyes!
So how did they do that?

  1. Automatic XML generation - you design the ribbon using a designer and the ribbon XML will be automatically created on run time.
  2. Generalizing method invocation - the ribbon XML contains a large amount of callbacks to define properties. For example - getLabel, getEnabled, getVisible and so on. It'll be more logical if these were exposed as real properties . This is what has been done here by implementing IReflect's invoke method.
  3. Automatically refresh the ribbon when needed - when a property is changed, the control is invalidated so the Ribbon can refresh itself.
  4. Full designer support - generating the xml on runtime led to the opportunity to give a designer support. You design on design time and your design is converted to the needed xml on runtime. Brilliant!

Demo

In the demo I've built a very small and targeted replica of the VSTO 3.0 Ribbon classes.
The demo persists of 3 projects -
* Ribbon - a class library that simulates the VSTO 3.0 ribbon class.
* SharedAddinDemo - a shared add-in project that extends Word applications (created using the Shared Add-in project type).
* SharedAddinDemoSetup - a setup project for the add-in that was added automatically after I had added the shared add-in project.

I'll go over the bullets from the last section and explain how they reflect in the demo.

Automatic XML Generation

I've created a base abstract class named BaseXmlWritingControl. Every ribbon control implements it. It has 4 methods: WriteStartXml, WriteXmlAttributes, WriteChildrenXml and WriteXml.
The 3 first methods are self-explanatory, WriteXml just gathers them all together and write an end element as well.
This way, if I call the ribbon's WriteXml, it'll generate the entire ribbon xml automatically (because WriteChildrenXml will go deeper and write the xml of the children and the children of the children and so on).

The shared add-in implements the IRibbonExtensibility interface and uses WriteXml to create the ribbon's xml on runtime:

#region IRibbonExtensibility Members

 

public string GetCustomUI(string RibbonID)

{

    return manager.RibbonXml;

}

 

#endregion

manager is the RibbonManager class which exposes the needed methods and services to the add-in project.

Generalizing Method Invocation

We have a finite amount of "events" that the ribbon xml gives us. This means that we can set the same callback method for all of the controls. When the callback is called, all we have to do is to find out which control is making the call and act accordingly.

I didn't go that deep during my presentation though. I only wanted to show how you can generalize the method invocation. I leave it to you to take this concept to the next level.

So what did I do there? The shared add-in project contains a CustomConnect.cs file. This is a partial class of the Connect class (only for convenience reasons). There I implement the IReflect interface.
We've said earlier that Office executes the callback methods using reflection. By implementing IReflect, we can control what will be executed when Office tries to invoke a certain callback. The IReflect invoke method will redirect calls from Office to different and more developer-friendly methods.

There is no need to implement all of the IReflect methods and properties. The most important methods for us are Invoke and GetMethods. GetMethods returns all of the method signatures to the caller. If a method does not appear in the returned list, Office won't even bother to send an Invoke request to the add-in.
Invoke redirects the call to the manager, giving it the name of the method to invoke and the args array. The manager then decided, according to the method name, which method to call.
The manager Invoke implementation (a very naive implementation):

public object Invoke(string name, object[] args)

{

    if (name.Contains("Loaded"))

    {

        officeRibbon.RibbonLoaded(args[0] as IRibbonUI);

 

        return null;

    }

 

    if (name.Contains("Label"))

    {

        return officeRibbon.Tab.Group.Button.GetLabel(null);

    }

 

    if (name.Contains("Button"))

    {

        officeRibbon.Tab.Group.Button.ButtonClick(null, null);

 

        return null;

    }

 

    return null;

}

Refreshing the Ribbon Automatically

When the ribbon is loaded, the onLoad event is raised. This event sends us an IRibbonUI object. This object has only 2 methods - Invalidate and InvalidateControl(string controlId). Calling Invalidate, refreshes the whole ribbon, InvalidateControl refreshes only the given control.
In order to save the ribbon object, I've added a RibbonLoaded method to the OfficeRibbon class that gets called on the onLoad event. All it does is to save the IRibbonUI object for future use:

public void RibbonLoaded(IRibbonUI ribbon)

{           

    this.ribbon = ribbon;

}

When a property of a control is set, we need to call the InvalidateControl so the ribbon will be refreshed and the changes will reflect there. This is what is being done on the RibbonButton.Label property:

public string Label

{

    get { return label; }

    set

    {

        label = value;

        ParentRibbon.Invalidate();

    }

}

Full Designer Support

After you create classes with properties for the available control types, adding designer support is easier. Designer support is a whole subject for itself so I won't dive into it now.

Conclusions

VSTO 3.0 Ribbon implementation is simple but genius. They used current abilities in order to create a better platform - the whole is greater than the sum of its parts.

What I want you to remember from this long article is not related to VSTO and how cool it is, I want you to remember that sometimes you can take the current design and build above it instead of rewrite it all. I want you also to remember that you can create an xml file to configure your application and even include callback names there. This can give your application some great flexibility and extensibility features.

I hope you've been enlightened,
Shay.

Share this post :

Give way to the yield keyword!

Yield! I ran into this keyword by accident (yield, accident... very funny), and I must say - this accident was a good one!
yield is a small keyword who has gotten used to live by the shadows of the celebrity keywords (static, const, Paris Hilton, Madonna, etc.), and I say – let's change it! Let's give yield what it deserves!

 

Why am I so thrilled about it?
OK, so let's introduce yield first – yield comes to help us to create an enumerator out of a single method.
For example, this code:

public static IEnumerable YieldTest(int num)

{

  for (int i = 0; i < num; i++)

  {

    yield return i;

  }

  yield break;

}     

 

static void Main(string[] args)

{

    foreach (int num in YieldTest(8))

    {

        Console.WriteLine(num);

    }

}

Will result in:

0
1
2
3
4
5
6
7
Press any key to continue . . .

As you could see, yield has 2 possible continuations – return and break:
yield return <something> means that <something> is going to be the next enumerator value.
yield break means that the party is over and so is our enumeration…

This means that yield return does not act as a regular return keyword - it doesn't really end the method's execution. yield return pauses the method execution and the next time you call it (for the next enumeration value), the method will continue to execute from the last yield return call. It sounds a bit confusing I think... Think of it that way - IEnumerator.MoveNext() really moves forward in the method till the next yield return\break statement.

Still asking yourself why am I so thrilled about my new precious keyword?
Well, this is a code saver! and I like code savers!

I can see it saves me code lines on 2 occasions:

1. When developing my very own enumerable object. See the difference in the next 2 samples:
A regular implementation (2 classes, 44 lines):

public class Users :IEnumerable

{

    // --- IEnumerable Members ---

 

    public IEnumerator GetEnumerator()

    {

        return new UserEnumerator(10);

    }

}

 

public class UserEnumerator : IEnumerator

{       

    private int m_index;

    private int m_maxIndex;

 

    private string GetUserName(int index)

    {

        return "User #" + index.ToString();

    }       

 

    public UserEnumerator(int maxIndex)

    {

        m_maxIndex = maxIndex;

        Reset();

    }       

 

    // --- IEnumerator Members ---

 

    public object Current

    {

        get { return GetUserName(m_index); }

    }

 

    public bool MoveNext()

    {

        m_index++;

        return (m_index < m_maxIndex);

    }

 

    public void Reset()

    {

        m_index = -1;

    }       

}

A yield implementation (1 class, 19 lines):

public class UsersYield :IEnumerable

{

    private string GetUserName(int index)

    {

        return "User #" + index.ToString();

    }   

 

    // --- IEnumerable Members ---

 

    public IEnumerator GetEnumerator()

    {

        for (int i = 0; i < 10; i++)

        {

            yield return GetUserName(i);

        }

 

        yield break;

    }

}

2. When developing a method that returns a list and I know that all I'm gonna do is loop over it. Here, the amount of code it saves is not as big as the in the previous bullet, but the code makes more sense, which is even better! For example:

private IEnumerable GetDaysOfWeek()

{

    yield return "Sunday";

    yield return "Monday";

    yield return "Tuesday";

    yield return "Wednesday";

    yield return "Thursday";

    yield return "Friday";

    yield return "Saturday";

    yield break;

}

 

public void LoopOverDaysOfWeek()

{

    foreach (string day in GetDaysOfWeek())

    {

        // do something               

    }

}

Did you notice in the last 2 sample codes that yield can return IEnumerator and IEnumerable? The fun just never stops!

So the yield keyword is indeed very helpful BUT, and it's a big but as you can see, be careful with it!
For instance, one can go and write the following code:

public IEnumerable BadYieldUsage()

{

    int i = 100;

    while (i > 0)

    {

        if (i % 2 == 0)

        {           

            if (i > 12)

            {

                yield return "Even";

            }

            else

            {

                yield break;

            }

        }

        else

        {

            yield return "Odd";

        }

        i--;

    }

}

I want to promise you – if you write a similar code block and actually use it, the end of the world, without any doubt, will come.
Keep the enumeration code as simple as you can because debugging it afterwards will turn you into a suicidal human being.

In conclusion, the yield keyword on the one hand, will save you lines of code, make it more readable in some cases and eventually make you happier. On the other hand, overusing it might kill you.

Fun fun fun!

Have fun!
Shay.

Share this post :
Posted by shayf | 21 comment(s)

Console.WriteLine("Hello World!");

Well... Hello there!

I'm Shay Friedman and this is the Big Bang post of my blog.
A bit about me - I've been around computers since the age of 8. I started to code when I was about 10 years old and as I turned 16, I started working in a company as a ColdFusion and ASP programmer. I got familiar with .Net during my army service. Since I finished my service, I've been working on various projects and platforms (Win, Web, Office, CRM) using .Net. Currently I work in ActionBase, which is a really challenging environment to work in (and really cool too!).

I'm going to write here about stuff that I find interesting and tips that I find useful.

Get ready to rumble!
Shay.

Posted by shayf | 1 comment(s)