mostlylucid

May 2005 Entries

Unemployed...

Well, I just finished my job at StormId (got a lovely bottle of whisky as a leaving present, yum!), I now have just under two weeks before I head down to Reading to start my new job with Microsoft. I intend to spend my time shedding a few pounds, getting as much driving tuition as possible (driving test on June 22nd…gulp!) and working on a few projects I’ve been neglecting. Hopefull you’ll notice improvements to this blog as well as a few other super-secret bits .
Anyone got any good books they’ve read recently…fiction or non?

The video gamre thing again...nothing to see here...

Look, I have to do it, I’m easily influenced and continually swept up by random waves of meme action…

 

What Video Game Character Are You? I am an Asteroid.I am an Asteroid.

I am a drifter. I go where life leads, which makes me usually a very calm and content sort of person. That or thoroughly apathetic. Usually I keep on doing whatever I'm doing, and it takes something special to make me change my mind. What Video Game Character Are You?

Cool little thing I keep losing...ObjectRepeater

This is a brilliant little server control from Rob van der Veer (found here) – which I’ve found lots of uses for but keep having to spend time tracking it down…so here it is, mainly for me but partly for you too  

///

    /// A templated databound repeater that dynamically determines which

    /// template to use based on the class of the object in the collection.

    ///

    [ParseChildren(false)]

    [ControlBuilder(typeof(ObjectRepeaterControlBuilder))]

    public class ObjectRepeater : System.Web.UI.Control, System.Web.UI.INamingContainer, IParserAccessor

    {

        private Hashtable _templates = new Hashtable();

        private string _defaultTemplateName = null;

        private IEnumerable _dataSource;

 

        public ObjectRepeaterDetermineTemplateDelegate DetermineTemplate;

        public event RepeaterItemEventHandler ItemCreated;

        public event RepeaterItemEventHandler ItemDataBound;

        public event RepeaterCommandEventHandler ItemCommand;

 

        #region Properties

 

        public string DefaultTemplate

        {

            get

            {

                return _defaultTemplateName;

            }

            set

            {

                _defaultTemplateName = value;

            }

        }

 

        public virtual IEnumerable DataSource

        {

            get

            {

                return _dataSource;

            }

            set

            {

                _dataSource = value;

            }

        }

 

        public ControlCollection Items

        {

            get

            {

                return this.Controls;

            }

        }

 

        #endregion

 

        #region Methods

 

        public void OnItemDataBound(RepeaterItemEventArgs e)

        {

            if(this.ItemDataBound != null)

                this.ItemDataBound(this, e);

        }

 

        public void OnItemCreated(RepeaterItemEventArgs e)

        {

            if(this.ItemCreated != null)

                this.ItemCreated(this, e);

        }

 

        public void OnItemCommand(RepeaterCommandEventArgs e)

        {

            if(this.ItemCommand != null)

                this.ItemCommand(this, e);

        }

 

        public override void DataBind()

        {

            // Controls with a data-source property perform their

            // custom data binding by overriding DataBind to

            // evaluate any data-binding expressions on the control   

            // itself.

            base.OnDataBinding(EventArgs.Empty);

 

            // Reset the control's state.

            Controls.Clear();

            ClearChildViewState();

 

            // Create the control hierarchy using the data source.

            CreateControlHierarchy(true);

            ChildControlsCreated = true;

 

            TrackViewState();

 

        }

 

        protected override void CreateChildControls()

        {

            Controls.Clear();

 

            if (ViewState["ItemCount"] != null)

            {

                // Create the control hierarchy using the view state,

                // not the data source.

                CreateControlHierarchy(false);

            }

        }

 

        ///

        ///

        ///

        /// True to create the hierarchy from the DataSource, False to create it from the ViewState.

        private void CreateControlHierarchy(bool useDataSource)

        {

            IEnumerable dataSource = null;

            int count = -1;

 

            if (useDataSource == false)

            {

                // ViewState must have a non-null value for ItemCount because this is checked

                //  by CreateChildControls.

                count = (int)ViewState["ItemCount"];

                if (count != -1)

                {

                    dataSource = new DummyDataSource(count);

                }

            }

            else

            {

                dataSource = this._dataSource;

            }

 

            if (dataSource != null)

            {

                int index = 0;

                count = 0;

                foreach (object dataItem in dataSource)

                {

                    CreateItem(index, ListItemType.Item, useDataSource, dataItem);

 

                    count++;

                    index++;

                }

            }

 

            if (useDataSource)

            {

                // Save the number of items contained for use in round trips.

                ViewState["ItemCount"] = ((dataSource != null) ? count : -1);

            }

        }

 

        private RepeaterItem CreateItem(int itemIndex, ListItemType itemType, bool dataBind, object dataItem)

        {

            RepeaterItem item = new RepeaterItem(itemIndex, itemType);

 

            RepeaterItemEventArgs e = new RepeaterItemEventArgs(item);

 

            //decide which template to use.

            string templateName = null;

 

            if(dataBind)

            {

                if(DetermineTemplate != null)

                {

                    templateName = this.DetermineTemplate(this, dataItem);

                    ViewState["templateName" + itemIndex.ToString()] = templateName;

                }

            }

            else

            {

                //determine template to use from viewState;

                templateName = (string)ViewState["templateName" + itemIndex.ToString()];

            }

 

            if(templateName == null)

                templateName = this.DefaultTemplate;

            ObjectTemplate dynamicTemplate = (ObjectTemplate)_templates[templateName];

 

 

            //Must exist.

            dynamicTemplate.ItemTemplate.InstantiateIn(item);

 

            if (dataBind)

            {

                item.DataItem = dataItem;

            }

            OnItemCreated(e);

            this.Controls.Add(item);

 

            if (dataBind)

            {

                item.DataBind();

                OnItemDataBound(e);

 

                item.DataItem = null;

            }

 

            return item;

        }

 

        protected override bool OnBubbleEvent(object source, EventArgs e)

        {

            // Handle events raised by children by overriding OnBubbleEvent.

 

            bool handled = false;

 

            if (e is CommandEventArgs)

            {

                RepeaterCommandEventArgs ce = (RepeaterCommandEventArgs)e;

 

                OnItemCommand(ce);

                handled = true;

            }

 

            return handled;

        }

 

 

        ///

        /// This member overrides Control.AddParsedSubObject.

        /// it catches the contents of each item.

        ///

        protected override void AddParsedSubObject(object obj)

        {

            if(obj is ObjectTemplate)

            {   

                ObjectTemplate template = (ObjectTemplate)obj;

                _templates.Add(template.Name, template);

                return;

            }

            else

            {

                if(!(obj is LiteralControl))

                    throw new Exception("ObjectRepeater can only have children of type 'ObjectTemplate'");

            }

            base.AddParsedSubObject(obj);

        }   

 

        #endregion

    }   

 

    public delegate string ObjectRepeaterDetermineTemplateDelegate(object sender, object dataItem);

 

    #region Control Builder

    ///

    /// Interacts with the parser to build a PanelBar control.

    ///

    public class ObjectRepeaterControlBuilder : ControlBuilder

    {

        ///

        /// This member overrides ControlBuilder.GetChildControlType.

        ///

        public override Type GetChildControlType(string tagName, IDictionary attributes)

        {

            // check is the tag is an TabStripPanelItem tag

            if (tagName.ToLower().IndexOf("objecttemplate") >= 0)

            {

                System.Diagnostics.Trace.WriteLine(tagName);

 

                // yes, so return TabStripPanelItem type

                return typeof(ObjectTemplate);

 

            }

            return null;

        }

 

        public override void AppendLiteralString(string s)

        {

            //empty implementation to drop literal content.

            System.Diagnostics.Trace.WriteLine(s);

        }

 

    }

    #endregion

 

    [ParseChildren(true)]

    public class ObjectTemplate : Control

    {

        private string _name;

        private ITemplate _itemTemplate;

 

        [TemplateContainer(typeof(RepeaterItem))]

        public ITemplate ItemTemplate

        {

            get { return _itemTemplate; }

            set { _itemTemplate = value; }

        }

 

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

    }

    internal sealed class DummyDataSource : ICollection

    {

        private int dataItemCount;

        public DummyDataSource(int dataItemCount)

        {

            this.dataItemCount = dataItemCount;

        }

        public int Count

        {

            get

            {

                return dataItemCount;

            }

        }

        public bool IsReadOnly

        {

            get

            {

                return false;

            }

        }

        public bool IsSynchronized

        {

            get

            {

                return false;

            }

        }

        public object SyncRoot

        {

            get

            {

                return this;

            }

        }

        public void CopyTo(Array array, int index)

        {

            for (IEnumerator e = this.GetEnumerator(); e.MoveNext();)

                array.SetValue(e.Current, index++);

        }

        public IEnumerator GetEnumerator()

        {

            return new BasicDataSourceEnumerator(dataItemCount);

        }

 

        private class BasicDataSourceEnumerator : IEnumerator

        {

            private int count;

            private int index;

            public BasicDataSourceEnumerator(int count)

            {

                this.count = count;

                this.index = -1;

            }

            public object Current

            {

                get

                {

                    return null;

                }

            }

            public bool MoveNext()

            {

                index++;

                return index < count;

            }

            public void Reset()

            {

                this.index = -1;

            }

        }

    }

Overcoming apathy

Well, it’s officially 1 week before I finish here…I currently have the problem of overcoming the apathy of working on a project which I’ll not see deployed before I leave. So far, refactoring to make it more straightforward to use by ‘those who will come after me’ (kind of like Deep Thought designing it’s replacement..only…not so impressive) has used up a fair bit of time, as has getting the system to be a bit more organised…
Ah well, I suppose I’d better revel in my current easy life – it certainly won’t be that way with my new employers .

My currentfavourite code thing...IXmlSerializable

Been using this a fair bit recently, allows complete control over the way a class serializes to XML – especially useful when using Dictionaries!

public class CountryDictionary : DictionaryBase, IXmlSerializable

    {

        public bool requiresSave = false;

        public Country this[long key]

        {

            get { return ((Country) Dictionary[key]); }

            set { Dictionary[key] = value; }

        }

 

        public ICollection Keys

        {

            get { return (Dictionary.Keys); }

        }

 

        public ICollection Values

        {

            get { return (Dictionary.Values); }

        }

 

        public void Add(long key, Country value)

        {

            Dictionary.Add(key, value);

        }

 

        public bool Contains(long key)

        {

            return (Dictionary.Contains(key));

        }

 

        public void Remove(long key)

        {

            Dictionary.Remove(key);

        }

 

        protected override void OnInsert(Object key, Object value)

        {

            if (key.GetType() != typeof (long))

                throw new ArgumentException("key must be of type long.", "key");

 

            if (value.GetType() != typeof (Country))

                throw new ArgumentException("value must be of type Country.", "value");

        }

        #region IXmlSerializable Members

 

        public void WriteXml(System.Xml.XmlWriter writer)

        {

           writer.WriteStartElement("Countries");

            foreach(Country country in this.Values)

            {

                writer.WriteStartElement("Country");

                writer.WriteAttributeString("iso3", country.Iso3);

                writer.WriteAttributeString("id", country.ObjectId.ToString());

                writer.WriteAttributeString("name", country.Name);

                writer.WriteAttributeString("active", country.Active.ToString());

                writer.WriteAttributeString("restricted", country.Restricted.ToString());

                writer.WriteAttributeString("shippingZone", country.ShippingZoneId.ToString());

                writer.WriteEndElement();

            }

            writer.WriteEndElement();

        }

 

        public System.Xml.Schema.XmlSchema GetSchema()

        {

            // TODO:  Add CountryDictionary.GetSchema implementation

            return null;

        }

 

        public void ReadXml(System.Xml.XmlReader reader)

        {

            bool saveNeeded = false;

            while (reader.Read())

            {

                if (reader.IsStartElement("Country"))

                {

                    long objectId = reader.GetAttribute("id") != null ? long.Parse(reader.GetAttribute("id") ) : 0;

                    Country country = new Country();

                    string name = reader.GetAttribute("name");

                    string iso3 = reader.GetAttribute("iso3");

                    bool active = reader.GetAttribute("active") != null ? bool.Parse(reader.GetAttribute("active")) : true;

                    bool restricted = reader.GetAttribute("restricted") != null ? bool.Parse(reader.GetAttribute("restricted")) : false;

                    long shippingZoneId = reader.GetAttribute("shippingZone") != null ? long.Parse(reader.GetAttribute("shippingZone")) : 0;

                    country.Name = name;

                    country.ObjectId = objectId;

                    country.Iso3 = iso3;

                    country.Active = active;

                    country.Restricted = restricted;

                    country.ShippingZoneId = shippingZoneId;

                   if(country.ObjectId ==0)

                    {

                        country.Save();

                        saveNeeded = true;

                    }

                    this.Add(country.ObjectId, country);

 

                }

                }

            this.requiresSave = saveNeeded;

        }

 

        #endregion

    }

So, as you can see it’s pretty simple, just letting you treat the serialization process as saving out a standard XML file…the actual serialization code is simple too:

/// <summary>

    /// Summary description for XmlCountryProvider.

    /// </summary>

    public class XmlCountryProvider

    {

 

        private static string filePath = Global.Config.CountryFile;

 

 

        private XmlCountryProvider()

        {

        }

 

        public static CountryDictionary Load()

        {

            XmlSerializer xser = new XmlSerializer(typeof(CountryDictionary));

            CountryDictionary fd = null;

 

            if(File.Exists(filePath))

            {

                using(TextReader tr = File.OpenText(filePath))

                {

                    fd = (CountryDictionary) xser.Deserialize(tr);

                }

            }

            return fd;

        }

 

        public static  void Save(CountryDictionary fd)

        {

            XmlSerializer xser = new XmlSerializer(typeof(CountryDictionary));

            using(TextWriter tw = File.CreateText(filePath))

            {

                xser.Serialize(tw,fd);

            }

        }

 

    }

 

So this essentially lets me very quickly save and load info from disk – not great when you need ‘db-type’ operations but it just rules when you need something to be easily editable…

What am I doing wrong??? CommunityServer issue...

I do intend to post this in the CommunityServer forums; just want to check I’m not being really dumb . Ok, this CS installation is at OrcsWeb so I have the default (System->Configuration) timezone set to -7…my user timezone (for myself) is set to GMT…problem is that my posts are taking 7 hours to appear…so my own timezone is ignored…anyone encountered this issue??? (Oh, I’ve set the time on this post to now-7 hours so it appears straight away…)

You just gotta love Slashdot...

Despite the probability of being labelled a Microsoft Fanboy, I am becoming less and less impressed with Slashdot (or more and more disappointed…same thing ). Now, I know that it’s really just an Linux propoganda outlet but I do still retain the vain hope that some balance can be found there (there’s VERY few blogs which are rabidly pro-microsoft and anti-linux for example…well Scoble excepting). The latest is an article on the MSN desktop search stuff, at the time I’m reading it there’s a bunch of comments for people who clearly haven’t even downloaded the tool with comments like this:
Great. Because, my biggest complaint about Microsoft is that the Web browsing isn't tightly integrated enough with the operating system yet. Now the innards of my computer can be thrown open to exploits like never before!
I’m sorry but that sort of comment doesn’t help anyone, Google search is WAY worse for this and there’s just no evidence that the MSN search toolbar has any integration with the browser at all.
Right, that’s it…when I reach the point that that site is just winding me up…time to stop reading it (oh, and for balance, I’ll also stop reading Scoble for a few weeks ).
Oh, and sorry about the site…no time to fix it right now but I’ll get on it as soon as I have time (I finish with my current employer on May 31st…the 2 weeks before I start with Microsoft…so things on the site WILL improve then; and I’ll also get a chance to post some more articles I’ve cobbled together!)

Comments now working...

Finally got comments working again for anonymous users…feel free to rant

&lt;uber:ASP.Net&gt; - Rewriting the URL using IHttpHandlerFactory

uber:asp.net- Rewriting the URL using IHttpHandlerFactory

This is a nice article on a technique I’ve used for a while not…and it’s really the only decent way to do this in ASP.NET…

I'll get back to normal posting soonish...

Just a lot going on in my life at the moment…will get back to this as soon as I can!

Odd question, anyone know how many shares Microsoft *currently* holds in Apple?

I know that 8 years ago, Microsoft bought $150m in Apple shares…at a time when the share price was VERY low; and effectively this purchase saved Apple. What I don’t know is whether MS sold it’s shares???

Asynchronous Client Script support Control for ASP.NET V2.0

Asynchronous Client Script support Control for ASP.NET V2.0

Really nice Async Client Script control for ASP.NET 2.0 – now why isn’t this in the core ASP.NET 2.0 framework?

Great articles on speeding up late binding

Brain.Save() - NPerfing Activator.CreateInstance()

Really nice comparison of the various methods of runtime creation of objects…

Hmm...wonder why my posts aren't appearing?

Slight wierdness with posts…another ‘glitch’ work out (probably something to do with timezones at a guess…)

Update in progress...

This is the first post on the new server…any glitches will be worked out over the weekend…

Is you can see this the new server works...

Few glitches which I’ll get sorted this weekend…

Tryin' out Community Server version

So, I think I’ve got this sucker working with CommunityServer ahead of my planned migration to a *proper* host this weekend. A few issues still – mainly around design and custom page elements I had on the old site…so an exciting weekend is ahead

Changes in the offing...

Well, I’ve finally decided that I need to move this blog to a more reliable provider, with that in mind I’ve bought hosting on OrcsWeb (most of my readers are in the states anyway…), plan is that I’ll spend a part of this weekend  migrating the site content over to CommunityServer ; between studying for my driving theory test next week.
So there *might* be some downtime this weekend while the domains shuffle around – but the result should be a far faster response and more bells and whistles on the eventual site (the Community server ‘pimpin’ scene has really taken off!)

Playing the end-game...

Well, it’s 26 days until I officially clock off for the last time at my current employer, unfortunately I’m now in that wierd period called ‘notice’. What makes this time so strange is that I still have a project to work on…the focus of which has changed now that I’m leaving – so obviously the focus is now getting it to a point for handover rather than finishing it.
So I’ve just had a bit of a ‘discussion’ with my manager over this – essentially I’m trying to do the best thing to try and get the project as far as possible, he’s trying to manage resources for handover which are not always exactly in-sync.
Anyway, long story short I’m going to have to chill a bit for the next month and forget a little about my usual ‘deliver at all costs’ approach to coding (a.k.a ‘heads down and screw the rest’). Hopefully I haven’t messed up my reference

Best resource for learning about System.Transactions

I’ve written about this topic in the past but by far the best resource for finding out about System.Transactions is this whitepaper by Juval Lowy.