Two simple reader Extension methods

Recently, I have added to my Extension Methods library a very useful ForEachLine methods, that extends the TextReader and FileInfo functionality.
The purpose of those methods is simple: provides ability to provide action to invoked for each line of a TextReader of file.

Here are the methods for anyone how find them useful, as well.

TextReader ForEachLine Extension Method

public static void ForEachLine(this TextReader reader, Action<string> action) {

 

    if (reader == null)

        throw new ArgumentNullException("reader");

    if (action == null)

        throw new ArgumentNullException("action");

    string line;

    while ((line = reader.ReadLine()) != null) {

        action(line);

    }

}

FileInfo ForEachLine Extension Method

public static void ForEachLine(this FileInfo file, Action<string> action) {

 

    if (file == null)

        throw new ArgumentNullException("file");

    using (StreamReader reader = file.OpenText()) {

        reader.ForEachLine(action);

    }

}

 

Hope this helps to anyone.

Happy coding ...

Posted by velio with no comments

Implementing ASP.NET XML providers - Part 1 (Persistance)

The built-in ASP.NET Membership, Roles, Profile providers fits into many Web site use-cases, but not all.
While I was wokring on some of my projects I have experienced the need of having a light ASP.NET providers pack.
Providers that work without database or additional services. Providers that can easy deploy with a Web site under restricted hosting environment.

The obvious solution was to implement ASP.NET Membership, Role, Profile providers base on XML file storages.

In this series I'll go through the steps of my implementation of ASP.NET XmlProviders.

Background

This ASP.NET Xml Providers pack is an evolution of examples, articles and samples of code which I have packed and improved for the needs of some of the projects I was working on.
In fact I'm pretty satisfied of using it on my projects, thus I have decided to share it and uploaded on Codeplex.

The Persistable base class

This article is about the base class for all XML storage classes.
First of all this is not invented originally by me.
I grab it from the net, made it generic, did some fixed and prepare it for synchronized usage.
I have implemented a simple, but robust caching in the Persistable class, in order to improve the performance.
In fact I'm using it as a base class in all my projects when I need fast and robust objects' persistance to XML files.

Here is the source code of Persistable class:

<-- >> code -->

/// <summary>

/// Generic class for a perssitable object.

/// Encapsulates the logic to load/save data from/to the filesystem.

/// To speed up the acces, caching is used.

/// </summary>

/// <typeparam name="T">class or struct with all the data-fields that must be persisted</typeparam>

public class Persistable<T> where T : new() {

 

    #region Static Fields ///////////////////////////////////////////////////////////

 

    public static readonly TimeSpan DefaultSlidingExpiration = TimeSpan.FromMinutes(30);

 

    #endregion

 

    #region Fields  /////////////////////////////////////////////////////////////////

 

    string _fileName;

    ReaderWriterLock _lock = new ReaderWriterLock();

    XmlSerializer _serializer;

    TimeSpan _slidingExpiration;

    [NonSerialized]

    object _syncRoot;

    T _value;

 

    #endregion

 

    #region Properties  /////////////////////////////////////////////////////////////

 

    /// <summary>

    /// Gets a value indicating whether this instance is empty.

    /// </summary>

    /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>

    protected virtual bool IsEmpty {

        get {

            return (_value == null || (_value is ICollection && (_value as ICollection).Count == 0));

        }

    }

 

    /// <summary>

    /// Gets a value indicating whether this instance is synchronized.

    /// </summary>

    /// <value>

    ///    <c>true</c> if this instance is synchronized; otherwise, <c>false</c>.

    /// </value>

    public virtual bool IsSynchronized {

        get {

            return false;

        }

    }

 

    /// <summary>

    /// Gets the sync root.

    /// </summary>

    /// <value>The sync root.</value>

    public virtual object SyncRoot {

        get {

            if (_syncRoot == null)

                Interlocked.CompareExchange(ref this._syncRoot, new object(), null);

            return _syncRoot;

        }

    }

 

    /// <summary>

    /// Gets or sets the data.

    /// </summary>

    /// <value>The data.</value>

    protected virtual T Value {

        get {

            if (IsEmpty) Load();

            return _value;

        }

        set { _value = value; }

    }

    #endregion

 

    #region Construct  //////////////////////////////////////////////////////////////

 

    /// <summary>

    /// Creates a instance of Persistable. Also creates a instance of T

    /// </summary>

    protected Persistable(string fileName, TimeSpan cacheSlidingExpiration) {

        _fileName = fileName;

        _serializer = new XmlSerializer(typeof(T));

        _slidingExpiration = cacheSlidingExpiration;

    }

 

    /// <summary>

    ///

    /// </summary>

    /// <param name="fileName"></param>

    protected Persistable(string fileName)

        : this(fileName, DefaultSlidingExpiration) {

    }

    #endregion

 

    #region Methods /////////////////////////////////////////////////////////////////

 

    /// <summary>

    /// Deletes the data from the cache and filesystem

    /// </summary>

    /// <returns></returns>

    public virtual bool Delete() {

 

        bool success = true;

        _lock.AcquireWriterLock(Timeout.Infinite);

        try {

            if (File.Exists(_fileName)) {

                try {

                    File.Delete(_fileName);

                }

                catch { success = false; }

            }

        }

        finally {

            _lock.ReleaseWriterLock();

        }

        return success;

    }

 

    /// <summary>

    /// Loads the data from the filesystem. For deserialization a XmlSeralizer is used.

    /// </summary>

    public virtual T Load() {

 

        _lock.AcquireReaderLock(Timeout.Infinite);

        try {

            if (System.IO.File.Exists(_fileName)) {

                using (FileStream reader = File.Open(_fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {

                    _value = (T)_serializer.Deserialize(reader);

                }

            }

            AddFileNotifier();

        }

        catch (Exception ex) {

            throw new Exception(

                string.Format("Unable to load persitable object from file {0}", _fileName), ex);

        }

        finally {

            _lock.ReleaseReaderLock();

        }

        return _value;

    }

 

    /// <summary>

    /// Persists the data back to the filesystem

    /// </summary>

    /// <param name="fileName">Name of the file.</param>

    public virtual void Save() {

 

        if (!IsEmpty) {

            _lock.AcquireWriterLock(Timeout.Infinite);

            try {

                string directory = Path.GetDirectoryName(_fileName);

                if (!Directory.Exists(directory))

                    Directory.CreateDirectory(directory);

                T value = _value;

                using (FileStream writer = File.Create(_fileName)) {

                    _serializer.Serialize(writer, value);

                }

            }

            catch (Exception ex) {

                throw new Exception(

                    string.Format("Unable to save persitable object to file {0}", _fileName), ex);

            }

            finally {

                _lock.ReleaseWriterLock();

            }

        }

    }

 

    #region - Cache -

 

    /// <summary>

    ///

    /// </summary>

    /// <param name="value"></param>

    void AddFileNotifier() {

        HttpRuntime.Cache.Insert(_fileName, new object(), new CacheDependency(_fileName),

            Cache.NoAbsoluteExpiration, _slidingExpiration, CacheItemPriority.Normal, new CacheItemRemovedCallback(OnFileChanged));

    }

 

    /// <summary>

    ///

    /// </summary>

    /// <param name="key"></param>

    /// <param name="value"></param>

    /// <param name="reason"></param>

    void OnFileChanged(string key, object value, CacheItemRemovedReason reason) {

        // invalidate value

        if (key == _fileName) _value = default(T);

    }

    #endregion

    #endregion

}

<-- << code -->

Points of Interest

You can find ASP.NET XmlProviders project and all the source code at http://codeplex.com/aspnetxmlproviders

File(s)

Persistable.zip

The robust MapPath

It is a common and often used scenatio in any kind of ASP.NET applications or libraries to get(map) the virtual path to a local file system path.
The standard way, and probably working fine for most of the cases, is to obtain the path through Server.MapPath(virtualPath).
However, the problem for me came when I need that in HTTP modules or handlers. I experienced a lot of “null reference” exceptions.
The reason: in the time when I need to obtain the local path, the Server instance for the current HttpContext wasn’t created and available.

First, I when to the common and obvious solution for that: implementing some helper methods to transfer the virtual path to a local one.
While using that I went through all the way of experiencing some problems, bug fixing. That approach involves as usual to keep the root of the local path somewhere in web.config (usually in appSettings), which then have to keep in mind to change when deploying the web application.
All the time, while experiencing that problem, I was wondering it should be a better solution and there should be something in ASP.NET I’m missing. I spend some time to go through the System.Web namespaces and classes and look for the proper solution and then “BINGO”, I found it.
I found (again, because I was using it to register custom VirtualPathProvider(s) so far) the wonderful class System.Web.Hosting.HostingEnvironment and its method (guess) MapPath. But cool thing about that is not giving any “null reference” exception even when used inside modules and handlers.

From the time I found it, I just used it anywhere (just in case) and no longer Server.MapPath().

Hope this helps.
Happy coding …

Posted by velio with no comments
Filed under:

Generic ASP.NET State Collection

Working on asp.net control libraries, I often needed to implement IStateManager for collections to persists in ViewState.
So, I have dicided this
a good cantidate for implementing it as a generic, instead of implementing type specific IStateManage collection.
Then I can use when I need it without a line of additional code.
And here is the result I came to:

Implemetation

using System;

using System.Collections.Generic;

using System.Text;

using System.Web.UI;

 

namespace Artem.Web.UI.Controls {

 

    /// <summary>

    ///

    /// </summary>

    /// <typeparam name="T"></typeparam>

    public class StateCollection<T> : List<T>, IStateManager where T : IStateManager, new(){

 

        #region Fields  /////////////////////////////////////////////////////////////////

 

        bool _tracking;

 

        #endregion

 

        #region Properties  /////////////////////////////////////////////////////////////

 

        /// <summary>

        /// When implemented by a class, gets a value indicating whether a server control is tracking its view state changes.

        /// </summary>

        /// <value></value>

        /// <returns>true if a server control is tracking its view state changes; otherwise, false.</returns>

        public bool IsTrackingViewState {

            get { return _tracking; }

        }

        #endregion

 

        #region Methods /////////////////////////////////////////////////////////////////

 

        /// <summary>

        /// Loads the state of the view.

        /// </summary>

        /// <param name="savedState">State of the saved.</param>

        public void LoadViewState(object savedState) {

 

            object[] state = savedState as object[];

            if (state != null) {

                T item;

                bool exists;

                for (int i = 0; i < state.Length; i++) {

                    item = (exists =( i < this.Count)) ? this[i] : new T();

                    item.LoadViewState(state[i]);

                    if (this.IsTrackingViewState)

                        item.TrackViewState();

                    if(!exists) Add(item);

                }

            }

        }

 

        /// <summary>

        /// When implemented by a class, saves the changes to a server control's view state to an <see cref="T:System.Object"/>.

        /// </summary>

        /// <returns>

        /// The <see cref="T:System.Object"/> that contains the view state changes.

        /// </returns>

        public object SaveViewState() {

 

            if (this.Count > 0) {

                int count = this.Count;

                object[] state = new object[count];

                for (int i = 0; i < count; i++) {

                    state[i] = this[i].SaveViewState();

                }

                return state;

            }

            else

                return null;

        }

 

        /// <summary>

        /// When implemented by a class, instructs the server control to track changes to its view state.

        /// </summary>

        public void TrackViewState() {

            _tracking = true;

        }

        #endregion

    }

}

 

Files

StateCollection.zip (.94 kb)

Hope this helps.
Happy coding ...

Posted by velio with no comments
Filed under: ,

Welcome

Hello and welcome to my blog.
This is my first post here and I look forward to find time keep it running with interesting and useful articles.

Best Regards,
See you around

Posted by velio with no comments
Filed under: