AJ's blog

November 24, 2006

Phantom property values

Filed under: .NET, .NET Framework, ASP.NET, C#, Design Time, Software Development — ajdotnet @ 11:40 pm

Here’s a quick tip for design time coders: Suppose you had a control or component and you would want to change a design time property from your code (say as reaction to a designer verb or the change of another property). Something like the following:

[ToolboxData(“<{0}:PropertyTextBox runat=server />”)]
public class PropertyTextBox : TextBox
{
    public string StandardCss { … }
    public string ErrorCss { … }
    
    bool _noCssHandling;
    public bool NoCssHandling
    {
        get { return _noCssHandling; }
        set
        {
            _noCssHandling = value;
            if (_noCssHandling)
            {
                _standardCss = “”;
                _errorCss = “”;
            }
        }
    }
}

Looks good? OK. Put it on your page, switch to design view, go to the property dialog, and change the two string members. Now switch to code view and you”ll see the respective attributes in the contol tag:

<cc1:PropertyTextBox ID=”PropertyTextBox1″ runat=”server” ErrorCss=”TextBoxError1″ StandardCss=”TextBox1″/>

Looks still good? OK. Switch to design view, change the property NoCssHandling to true, and enjoy the fact that the other two properties are miraculously set to empty.

Looks still good? Still content? Well, just for the fun of it switch to code view…

<cc1:PropertyTextBox ID=”PropertyTextBox1″ runat=”server” ErrorCss=”TextBoxError1″ NoCssHandling=”True” StandardCss=”TextBox1″/>

Wait a moment! Empty strings are not supposed to contain old values, right? You could even debug the code and verify that the dependend properties have been set and returned the correct values. And yet, within the markup code of your .aspx file the repective HTML attributes remain unchanged.

Catching the phantom

The reason for this effect is … I may have mentioned that before 😉 … design time is different. At runtime you have only one instance of your object. At design time there may be phantoms, ghosts and astral bodies – different incarnations of the same object, shadows that reflect different time spans. There is but one file, but what you see is just one of possibly many presentations of that file in the appearance in which the current designer presents it. This may be the .aspx markup view, the design surface, the property dialog, the code view, the component view.

If one designer triggers a change on your object, none of the other designers knows about it. And thus, none will reflect that change, leaving the different designers in an inconsistent state. The trick is to announce the change to the other designers and the means to do that is the IComponentChangeService interface. (This is something you would only want to happen at design time to avoid unexpected behaviour at runtime.)

BTW: This is called Document/View concept, a derivation of the Model/View/Controller pattern and well known from MFC. No fairies or other surreal creatures. No leprechauns either, what a pity.)

Here is a version that takes the design time requirements into account: 

public bool NoCssHandling
{
    get { return _noCssHandling; }
    set
    {
        _noCssHandling = value;
        if (_noCssHandling)
        {
            if ((this.Site != null) && (this.Site.DesignMode))
            {
                SetValue(this, GetPropertyDescriptor(this, “StandardCss”), “”);
                SetValue(this, GetPropertyDescriptor(this, “ErrorCss”), “”);
            }
            else
            {
                _standardCss = “”;
                _errorCss = “”;
            }
        }
    }
}

static PropertyDescriptor GetPropertyDescriptor(IComponent component, string property)
{
    PropertyDescriptorCollection properties =
        TypeDescriptor.GetProperties(component.GetType());
    foreach (PropertyDescriptor pd in properties)
    {
        if (pd.Name == property)
        return pd;
    }
    return null;
}

static void SetValue(IComponent component, PropertyDescriptor pd, object value)
{
    object oldValue = null;
    IComponentChangeService componentChangeService = (IComponentChangeService)
        component.Site.GetService(typeof(IComponentChangeService));
    
    if (componentChangeService != null)
    {
        try
        {
            // rememeber old value
            oldValue = pd.GetValue(component);
            // announce before change
            componentChangeService.OnComponentChanging(component, pd);
        }
        catch (CheckoutException ex)
        {
            // under source control, the checkout may be canceled by the user
            if (ex != CheckoutException.Canceled)
                throw;
        }
    }
    
    try
    {
        // try to set new value
        pd.SetValue(component, value);
    }
    catch
    {
        value = oldValue;
        throw;
    }
    finally
    {
        // announce after change
        if (componentChangeService != null)
            componentChangeService.OnComponentChanged(component, pd, oldValue, value);
    }
}

Well, that’s fairly much code just to set a property value. And to announce it to the design time environment. And to take source control and other effects into account. And it’s not even property specific? Wow. Reusable and a good candidate for a helper class. Not much code if you really think about it.

From now on, your property value changes at design time will be properly advertised to all designers and they will happily reflect those changed values.

That’s all for now folks,
AJ.NET

Advertisements

November 18, 2006

More (on) type converters

Filed under: .NET, .NET Framework, ASP.NET, C#, Design Time, Software Development — ajdotnet @ 4:15 pm

After the last post I thought I might come up with some real world examples. Just to give you an idea how usefull type converters can be at design time.

Configured lists

There are various situations where a string property should be set to a value from a given set (if only non-exclusive default values to speed up typing), the set being (made) available in some kind of configuration file. Examples I encountered so far include:

In this case a type converter that reads an the web.config and returns the /configuration/appSettings/add/@key values solves the first demand. The step to a type converter base class that reads any xml file and provides a list of values according to some XPath expression is no rocket science. Given that base class any of those examples can be implemented using a simple derived class that only has to specify the file and XPath.

Artificial Enumerations

Consider the following (quite common) situation: You have an enumeration of certain values for some property of your component. The component shall act as base class and will be extended in different contexts. For example, a database action enumeration could include values like Save, Delete and Update.
The first approach that comes to mind would be to define a C# enumeration and the respective property. Afterwards your property can be set in the properties pane, the pane will automatically present a drop down list of the enumeration values, not allowing any other input. Of course working on the code level with eumerations is type safe and supported with intellisense.

However there is also a serious issue: The set of valid values for that property cannot be extended. .NET does not support something like inherritance of enumerations. If the derived class should need additional values one could either provide some special enumeration value in the base class for future use (some kind of “Custom”) and add an additional property to describe that custom value (making the act of describing the database action a two-stage process), or extend the enumeration with the custom value itself (spoiling the base class with information of derived functionality, making it visible to any other derived class and causing maintenance hurdles).

One could also revert to using a string instead of an enumeration. This would allow free choice of values and keep the base class clean of special cases. On the down side would be the lack of design time support, intellisense support (this could be solved with constants, yet this doesn’t help within the designer), and the need to remember all valid values in a given context. I see typos having a party…

Frankly, if these are the alternatives, I would prefer the spoiled enumeration.

However, a TypeConverter can help with these issues:
First, some attributes could describe the valid values of a property (they have to be specified somehow and an attribute looks good for me). A derived class could use one of these attributes to extend the set defined by the base class (say an attribute at the class level could take the name of the property and the additional values).
A type converter could then examine the property (the information is available through the context parameter) and the respective attributes along the inherritance hierarchy to build up a list of values which in turn causes the property grid to show a drop down list at design time. What’s more, the list will vary depending on the context, showing only the values that make sense in the given situation. Voilá, a string property with “extendable enumeration behaviour” at runtime.

Reflection information

Sometimes one needs to specify types (for dynamically created objects), methods (to be invoked dynamically), or properties (to get data from). All respective candidates (say all properties of an object) can be made available at designtime, given the right type converter.

Solution or project information

For navigation to another page it would be usefull to have a list of .aspx files in your project to select the page at design time. A type converter could get this list using the Visual Studio automation model.
This area is especially usefull if you are working with the Guidance Automation Toolkit (GAT) where type converters play a role in providing and converting informations for and from wizards. Examples include a list of projects, base classes, or the conversion of a project folder to a respective namespace for a new class.

Real type conversion

We should not forget the function type converters have by name. If you have a look at a windows form control at design time (the windows forms designer seems to make better use of this than the webforms designer), you will notice that you can type in something like “75;50” in the properties pane for the Size property. You may also click on the little + and set the Width and Height property directly. The ability to set the values of contained properties (in this case Width and Height) on the object itself (in this case Size) comes with a … guess what? … type converter. In this case it converts the string with two numbers to an instance of the Size struct and vice versa.
Thus type converters can help to simplify the modification of properties of complex structs.

Code? Sorry, not this time. These are all real world examples from actual projects. I can share knowledge and experience but not customers’ code.

That’s all for now folks,
AJ.NET

November 11, 2006

Reach out at design time

Filed under: .NET, .NET Framework, ASP.NET, C#, Design Time, Software Development — ajdotnet @ 6:05 pm

Some developers are not even aware that their code actually runs at design time. Others try to ignore that fact as long as possible. One reason for this is probably this: design time is different. Not just “not runtime”, but really different. The weird kind of different. Like Babylon 5 hyperspace where physical laws don’t apply. Objects get instantiated with the type of their base class, some events occure while others don’t, types may not be available or change their version, data that depends on configuration will be unconfigured, context information available at runtime will not be present, and so on.

There are usually two reasons to have to look into design time: One is some issue at design time, e.g. a control that no longer renders itself properly. The other is the desire to provide better design time support.

There are several “levels of design time involvement” of your code:

  1. Regular code that does not run at design time. We can safely ignore this code from now on. It’s still worth mentioning since it is sometimes quite important to know whether the code will be called or not (e.g. in the case of certain events).
  2. Regular code that runs at design time and may need to protect itself for unexpected context data. This is usually adressed with defensive programming style (check every object, don’t expect certain contexts, e.g. a request, etc.) or with explicitely checking for design time (i.e. testing Component.Site.DesignMode)
  3. Regular code that is (perhaps primarily) intended to be used at design time (yet still may play a role at runtime). TypeConverters are a perfect example since they are used at design time to check inputs within the properties pane and also to provide the values shown in the drop down list of the property (e.g. for properties of an enumeration type).
  4. Code that uses the design time services offered by the environment (i.e. the .NET Framework based design time support). This code can run only in design time and plays no role at runtime. The design time services are available with calls to GetService (offered by various objects within the design time model).
  5. Code that also uses the Visual Studio automation model. While the design time services offer only limited support, the automation model (based on COM and also available to VBA) open up the whole Visual Studio as playground, including access to the solution structure.

Let’s look into these levels with some concrete examples:

1. Regular code not running at designtime

Done. 🙂

2. Regular code running at designtime

Have look at the following label class, intended to show the current request URL:

[ToolboxData(“<{0}:UrlLabel runat=server />”)]
public class UrlLabel : Label
{
    public string CurrentUrl
    {
        get { return this.Page.Request.Url.AbsoluteUri; }
    }
    
    public override string Text
    {
        get { return CurrentUrl; }
    }
}

This innocent looking code will work properly at runtime, yet at design time it looks like this:

The reason is that the accessed objects in the property are not what they are expected to be. The page may be there but in case you don’t know, the actual page class is the base class of the class used at runtime. And of course the request object is null, since there is no request. Here’s a version of the property that adresses these issues:

public string CurrentUrl
{
    get
    {
        if ((this.Site != null) && this.Site.DesignMode)
            return http://www.designtime-is-fun.com&#8221;;
        return this.Page.Request.Url.AbsoluteUri;
    }
}

This solved the problem at design time:

At runtime, both versions look the same:

Better?

3. Regular code that supports design time

There’s plenty of areas to support the design time experience. The most commonly used things are attributes on classes and properties and TypeConverters. TypeConverters are used at design time to check the values typed in the properties pane and also to provide the content of a drop down list provided there. Of course they stilll have value at runtime, e.g. to interpret configuration data.

public class NamesTypeConverter : TypeConverter
{
    public override bool GetStandardValuesSupported
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesExclusive
        (ITypeDescriptorContext context)
    {
        return false;
    }
    public override StandardValuesCollection GetStandardValues
        (ITypeDescriptorContext context)
    {
        StandardValuesCollection values =
            new StandardValuesCollection(new string[] { “Alex”, “John”, “Steve”, “Zoe” });
        return values;
    }
}

[ToolboxData(“<{0}:NameLabel runat=server />”)]
public class NameLabel : Label
{
    string _owner= “<no owner>”;
    
    [TypeConverter(typeof(NamesTypeConverter))]
    public string Owner
    {
        get { return _owner; }
        set { _owner = value; }
    }
    
    public override string Text
    {
        get { return Owner; }
    }
}

This will offer the following drop down list at design time:

Gee, a string property and still a drop down list with several predefined choices!

4. Code using design time services

Sooner or later one needs information from the design time environment or would like to react on some events (e.g. the addition af a new control at design time). Unfortunately the area of design time services is also the area where the documentation begins to get sparse. Some areas are well documented, others are not. Especially the background story definitely lacks some information.

This TypeConverter offers a list of IDs of textboxes and is used by a label that simply shows the content of that textbox.

public class TextBoxIDsTypeConverter : TypeConverter
{
    public override bool GetStandardValuesSupported
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesExclusive
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues
        (ITypeDescriptorContext context)
    {
        if (context == null)
            return null;
        
        IDesignerHost host =
            (IDesignerHost)context.GetService(typeof(IDesignerHost));
        Control parent = host.RootComponent as Control;
        List<string> list= new List<string>();
        foreach (Control control in parent.Controls)
        {
            if (control is TextBox)
                list.Add(control.ID);
        }
        list.Sort();
        StandardValuesCollection values =
            new StandardValuesCollection(list);
        return values;
    }
}

[ToolboxData(“<{0}:TextboxLabel runat=server />”)]
public class TextboxLabel : Label
{
    string _textbox= “textbox_id”;
    
    [TypeConverter(typeof(TextBoxIDsTypeConverter))]
    public string Textbox
    {
        get { return _textbox; }
        set { _textbox = value; }
    }
    
    public string TextboxText
    {
        get
        {
            if ((this.Site != null) && this.Site.DesignMode)
                return “<textbox text>”;
            TextBox t = (TextBox)this.Page.FindControl(_textbox);
            if (t==null)
                return “<textbox “+_textbox+” not found>”;
            return t.Text;
        }
    }
    
    public override string Text
    {
        get { return TextboxText; }
    }
}

This will offer a list of textboxes on the same page:

It even works at runtime, like the following snapshot taken after a postback shows:

We are beginning to build up relationships.

5. Code using the Visual Studio automation model

The design time services are somewhat limited in what they offer. For example there is no service that tells one what file he is working on. Within the design time model this information is not even available. But it is available outside, within the Visual Studio automation model. It’s hardly documented (unless you peek at the Visual Studio SDK documentation) but all you have to do is to ask for the DTE interface which recides in the EnvDTE assembly.

public class TextfileTypeConverter : TypeConverter
{
    public override bool GetStandardValuesSupported
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesExclusive
        (ITypeDescriptorContext context)
    {
        return false;
    }
    public override StandardValuesCollection GetStandardValues
        (ITypeDescriptorContext context)
    {
        if (context == null)
            return null;
        
        DTE dte = (DTE)context.GetService(typeof(DTE));
        Project p = ((object[])dte.ActiveSolutionProjects)[0] as Project;
        string filename = Path.Combine(p.FileName, “prefixes.txt”);
        string[] lines = File.ReadAllLines(filename);
        
        StandardValuesCollection values =
            new StandardValuesCollection(lines);
        return values;
    }
}

[ToolboxData(“<{0}:PrefixedLabel runat=server />”)]
public class PrefixedLabel : Label
{
    string _prefix= “PREFIX:”;
    
    [TypeConverter(typeof(TextfileTypeConverter))]
    public string Prefix
    {
        get { return _prefix; }
        set { _prefix = value; }
    }
    
    public override string Text
    {
        get { return _prefix + base.Text; }
        set
        {
            if (value.StartsWith(_prefix))
                value = value.Substring(_prefix.Length);
            base.Text = value;
        }
    }
}

Given a textfile named prefixes.txt in the web project with the respective content it will look like this:

Great, we cannot only provide a list of choices, we can even edit this list by means of a simple text file.

So, now you are free to do what you want. Your code is in control and you can reach wherever you want. However you still need the Visual Studio to call your code and unless you knock it down it will eventually have to return (or be brought back). The next level that does not suffer from those limitations will be any kind of Visual Studio AddIn. But that’s another story.

That’s all for now folks,
AJ.NET

November 3, 2006

Logging? Efficiently please!

Filed under: .NET, .NET Framework, Software Development — ajdotnet @ 9:58 pm

Logging is important. It allows post mortem analysis of your code. Be it for error diagnosis, to get an impression of the runtime characteristics, to trail some users work. Logging is but one option if it comes to detecting concurrency issues or in production where it is no option to attach a debugger. Logging in production of course requires the logging features to be present in release builds, yet they should have minimal performance impact if logging is switched off.

Logging is also no simple thing to do, for there are so many things to consider: Trace level, granularity, extensibility, where to log, how to configure, … . So it is prudent to check if someone has already done this work. There are actually several options, for example:

Using log4net

What do you use for logging? Log4net? Me to. Log4net is mature, easy to use, highly configurable, supports different log styles and log stores for the information, and it is kind of a standard. It is what I called in a previous post a “good framework”.

Logging with log4net is as easy as the following example, taken form the log4net manual:

using log4net;

namespace Com.Foo
{
    public class Bar
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
        
        public void DoIt()
        {
            log.Debug(“Did it again!”);
        }
    }
}

They also adress the issue of performance:

“The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows that the speed of logging (or rather not logging) is crucial. ” (log4net features)

And they provide a respective example in the log4net faq:

What is the fastest way of (not) logging?
For some logger log, writing,

log.Debug(“Entry number: ” + i + ” is ” + entry[i]);

incurs the cost of constructing the message parameter, that is converting both integer i and entry[i] to a string, and concatenating intermediate strings. This, regardless of whether the message will be logged or not.

If you are worried about speed, then write

if(log.IsDebugEnabled)
{
    log.Debug(“Entry number: ” + i + ” is ” + entry[i]);
}

This way you will not incur the cost of parameter construction if debugging is disabled for logger log. […] 

Easy to use and performance aware, right? Well, would I be asking that question if the answer where a confident “yes”?

A better way of using log4net

Whenever I began looking at performance characteristics in a project, logging in this naive way (sorry, no offense intended) was one of the first things to show up. Many projects react with simply removing logging from release builds altogether, carelessly giving away a powerfull tool – sometimes the only one – to diagnose their application in production.

The general issues with the proposed “speed optimized” version above are:

  1. it is twice as much code lines per log statement (4 times if you count the curly braces)
  2. it is a recommendation, not a mandatory – not to mention enforced – way of logging
  3. it optimizes the usage of log4net, yet it falls short in properly observing the performance recommendations for .NET

Sidenote: It is a recomendation in .NET to avoid concatenating several string using the + operator. Rather one should use String.Concat or (with growing degree of complexity) String.Format or the StringBuilder class.

Actually this is not he only project ported from java to .NET that needs another step of “.NETification” after the first migration is done. I encountered similar issues in Spring.NET and their somewhat naive usage of reflection. NUnit for example has undergone this step: “It is written entirely in C# and has been completely redesigned to take advantage of many .NET language features, for example custom attributes and other reflection related capabilities. “

To look a bit deeper at my concerns and come up with a solution, let’s look at a slightly more complex example. Within a page class I would like to log the current request, user and possibly some error. Following the log4net documentation the code would look like this:

public class MyPage : Page
{
    private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
    
    override protected void OnInit(EventArgs e)
    {
        if ((log!=null)) && log.IsDebugEnabled)
        {
            log.Debug( “Url: “ + HttpContext.Current.Request.RawUrl +
                ” User: “ +Thread.CurrentPrincipal.Identity.Name);
        }
        
        try
        {
            base.OnInit(e);
        }
        catch (Exception ex)
        {
            if (log!=null
                log.Error( “Exception in Page.OnInit”, ex);
            throw;
        }
    }
}

Note that I did additional checks for null. The log4net documentation does not state that GetLogger will always return a none-null value. Following defensive programming style I like to make sure a future version of log4net will not break my code.

Because logging is such a frequent thing to do I resent every line of code beyond the logging call itself. And I expect the framework to take whatever I have to log rather than having me shape the data for it. In more detail:

  1. I don’t like the lingering log member. The first logging attempt will take the additional effort to remember the details of logging, go to the top of the souce file, add that member, go back to the original location in the file, and only then one will be able to finally log the data. (Am I being lazy? Sure I am. Laziness is one of the best qualities a good developer should have!)
  2. I don’t like to check the trace level. Why do I have to do this just because of performance? There’s a framework. It should do that and it should do it right in the first place.
  3. I don’t like this form of string concatenation. I would like the comfort of a format string. Yes, I could call String.Format. But this surely is a performance issue and again, there’s a framework to do that for me.

In accordance with my “write the client code first” approach (previous post), here is what I would expect to do:

public class MyPage : Page
{
    override protected void OnInit(EventArgs e)
    {
        LogHelper.DebugFormat(this, “Url: {0}; User: {1}”,
            HttpContext.Current.Request.RawUrl, Thread.CurrentPrincipal.Identity.Name);
        
        try
        {
            base.OnInit(e);
        }
        catch (Exception ex)
        {
            LogHelper.Error(this, ex, “Exception in Page.OnInit”);
            throw;
        }
    }
}

Looks better? You bet. However in order to work the LogHelper class is needed, one that also meets my expectations. One that looks a little like this:

public class LogHelper
{
    [Conditional(“TRACE”)]
    public static DebugFormat(object context, string format, params object[] args)
    {
        ILog log = LogManager.GetLogger(context.GetType());
        if ((log==null)) || !log.IsDebugEnabled)
            return;
        string msg= string.Format(format, args);
        log.Debug(msg);
    }
    
    [Conditional(“TRACE”)]
    public static Error(object context, Exception ex, string msg)
    {
        ILog log = LogManager.GetLogger(context.GetType());
        if ((log==null)) || !log.IsErrorEnabled)
            return;
        log.Error(msg, ex);
    }
    
    […]
}

Of course LogHelper should provide a bunch of other overloads:

  • overloads that take a string or type as context, to be called by static members
  • overloads that take single messages as well as a parameter lists for string concatenations
  • overloads for efficient string formating
  • overloads for type safety
  • trace level checks for special cases
  • there could be methods that are only available in debug mode

So, what has been gained by this?

  1. Wherever I want to log something, I can do it right away. The only price for calling a static method rather than an instance is an additional parameter context to pick the logger instance.
  2. Due to the different overloads I can pass the information as I have it, relieving me of the work to prepare it for the logger.
  3. The different overloads also lay the foundation for doing the trace level check within the helper class, before the cost of preparing the data (e.g. calling String.Format) has been taken.

In other words: I have to write considerably less code (logging code down by 50% and preparational code eliminated altogether). The code automatically observes the log4net recommendation for fast (not) logging and it also observes the .NET recommendation for efficient code. And last not least, it provides a multitude of logging methods tailored to my particular needs (something that is no viable option for an interface).

But wait, there’s even more! There are other logging services that can be adressed far easier in one central location. E.g.:

  • Some of the helper methods could add code to enrich the information. Especially error logs could be amended with current request, user, appdomain name, session id, … .
  • Some people do like method entrance/exit traces to get detailed information about the flow of control. There could be special methods tailored to that need and perhaps a special switch to distincly control it. (That switch is for me, to switch that feature off! 😈 ) 
  • There’s allways the need to trace some data in more deepth. There could be helper methods that trace the complete current request information, the contents of the ASP.NET cache or session, the contents of a collection, arbitrary objects (reflecting all members), stack trace, …
  • The class could register itself automatically for system events (such as error events) and thus trace application or page livecycles.
  • Log4net has a problem when several instances are initialized with the same configuration and trying to write to the same files. (Which will happen in any ASP.NET application due to app domain recyclings, not to mention web garden scenarios). This can be adressed in the helper once and for all.

See, log4net is good, but there is still room for a framework upon it. OK, that’s a very elaborate posting for something as simple as logging. Take it as a real world example of some of the principles outlined in the previous post (notably #1, but #3 and #0 as well).

That’s all for now folks,
AJ.NET

Blog at WordPress.com.