Wednesday, August 20, 2008

XML sorting using LINQ to XML

This is a quick method of sorting elements in a XML document using LINQ to XML.

Let's take the following XML document as an example:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <node>3</node>
  <node>4</node>
  <node>1</node>
  <node>2</node>
  <node>5</node>
</root>

We want to sort nodes in alphabetical order.

Below is the magic code that does this:

XDocument xml = XDocument.Load("XMLFile.xml");
xml.Root.ReplaceNodes(xml.Root.Elements("node").OrderBy(el => el.Value));
xml.Save("XMLFile.xml");
 

This is a very simple example that can be extended to match your needs.

Thursday, March 20, 2008

Generic abstract factory base class (C# 3.0, LINQ)

In almost all projects in which I participated at some point there was a need for a factory implementation.

There is already a pattern concept about factory, but it is not always the best solution. The solution proposed below is a particular approach (general and flexible) of the pattern concept.

The purpose of this solution was not to implement the original pattern, but to give an alternative implementation based on some of the pattern's exposed principles.

With this current factory implementation the idea is to have a base class and derived classes so that at some point to be able to get the instance of a derived class based on an identifier (not the class type, a label).

To exemplify such a need here is a small example: we have a base class called ImageBase and the derived classes called JPEG, GIF, etc. We have the image stored somewhere and we need to load it based on a label/identifier. It’s identifier comes from a different source (database, config file..). A quick solution is to make a method that will return an instance of the ImageBase class based on a parameter:

public static class Factory
{
    public static ImageBase Create(ImageType type)
    {
        switch (type)
        {
            case ImageType.BMP:
                return new ImageBMP();
            case ImageType.GIF:
                return new ImageGIF();
            case ImageType.JPEG:
                return new ImageJPEG();
            default:
                return null;
        }
    }
}

This seems to be a good and apparently quick solution, but when we want to support new image types this method must be modified in order to support/include the new types.

The solution I propose is based on labeling implementation classes with a custom Attribute for specifying implementation type (JPEG, GIF). When the factory is called it will receive a label and will return the instance of the corresponding implementation (marked with the label given as parameter).

public abstract class Factory<TDescriber, TBase>
{
    // list of assemblies to search in for implemented classes
    List<Assembly> searchAssemblies;

    //cached implementations
    Dictionary<TDescriber, RuntimeTypeHandle> implementationList;

    readonly object cacheLock = new object();

    protected Factory()
    {
        searchAssemblies = new List<Assembly>();
    }

    public abstract TBase Create(TDescriber label);

    protected TBase CreateImplementation(TDescriber label)
    {
        Type implementation = GetImplementationType(label);
        return (TBase)Activator.CreateInstance(implementation);
    }

    protected Type GetImplementationType(TDescriber label)
    {
        RuntimeTypeHandle handle = GetImplementationFromCache(label);
        return Type.GetTypeFromHandle(handle);
    }

    RuntimeTypeHandle GetImplementationFromCache(TDescriber label)
    {
        if (implementationList == null)
        {
            lock (cacheLock)
            {
                if (implementationList == null)
                {
                    implementationList = new Dictionary<TDescriber, RuntimeTypeHandle>();

                    //if no assemblies are defined for search add executing assembly
                    if (searchAssemblies.Count == 0)
                        searchAssemblies.Add(Assembly.GetExecutingAssembly());

                    BuildCache();
                }
            }
        }

        if (implementationList.ContainsKey(label))
        {
            return implementationList[label];
        }
        else
        {
            throw new Exception("Cannot find type");
        }
    }

    protected List<Assembly> SearchAssemblies
    {
        get { return searchAssemblies; }
    }

    void BuildCache()
    {
        Type attributeType = typeof(FactoryLabelAttribute);
        Type baseType = typeof(TBase);
        bool isBaseInterface = baseType.IsInterface;

        //search all assemblies and types
        var implementations = from assembly in searchAssemblies
                              from selType in assembly.GetTypes()
                              let attribute = Attribute.GetCustomAttribute(selType, attributeType) as FactoryLabelAttribute
                              where (attribute != null && attribute.Label is TDescriber) && (isBaseInterface ? selType.GetInterfaces().Contains(baseType) : selType.IsSubclassOf(baseType))
                              select new { Type = selType, Describer = attribute.Label };

        //add results to cache
        foreach (var foundImplementation in implementations)
            implementationList.Add((TDescriber)foundImplementation.Describer, foundImplementation.Type.TypeHandle);
    }
}
Some observations about this solution:
  • Each implementation will add the FactoryLabel attribute which will specify the type that is implemented and derived from the base class.
  • CreateImplementation method returns an instance of the implementation matching the label parameter.
  • GetImplementationType method returns the type of the implementation which matches the label parameter
  • When CreateImplementation or GetImplementationType is called first time a dictionary of Label – Type will be built. This dictionary acts like a cache for further requests.
  • Implementation classes can be present in different assemblies. In this case a list of containing assemblies can be passed to factory. This list of assemblies is used to search for implementations. If no assembly is pointed, executing assembly is used to search for implementations.
  • RunTypeHandler is used instead of Type, because for caching purpose is more lightweight than the Type.
  • FactoryLabelAttribute takes an object for implementation identification. Practically this should be a value type (int, double, enum).

Bellow you can find some samples of this approach:

public abstract class ImageBase
{
    public abstract void Test();
}

public enum ImageType
{
    GIF,
    BMP,
    JPEG
}

[FactoryLabel(ImageType.JPEG)]
public class ImageJPEG : ImageBase
{
    public override void Test()
    {
        Console.WriteLine("JPEG type");
    }
}

[FactoryLabel(ImageType.BMP)]
public class ImageBMP : ImageBase
{
    public override void Test()
    {
        Console.WriteLine("BMP type");
    }
}

[FactoryLabel(ImageType.GIF)]
public class ImageGIF : ImageBase
{
    public override void Test()
    {
        Console.WriteLine("GIF type");
    }
}
public class ImageFactory : Factory<ImageType, ImageBase>
{
    static readonly ImageFactory instance = new ImageFactory();

    public static ImageFactory Instance { get { return instance; } }

    private ImageFactory()
    {
        SearchAssemblies.Add(typeof(ImageBMP).Assembly);
    }

    public override ImageBase Create(ImageType label)
    {
        return CreateImplementation(label);
    }
}
static void DoTestFactory()
{
    ImageBase gif = ImageFactory.Instance.Create(ImageType.GIF);
    gif.Test();
    ImageBase bmp = ImageFactory.Instance.Create(ImageType.BMP);
    bmp.Test();
    ImageBase jpeg = ImageFactory.Instance.Create(ImageType.JPEG);
    jpeg.Test();
}

This might not be the perfect solution but is a point of start in creating a generic factory adapted to your needs.

Tuesday, March 18, 2008

Entity Framework and connections

Recently I began to play with ADO.NET Entity Framework Beta 3. I didn't liked the way of setting connections. My requirements were not to add new lines to existing config file, just to use existing defined connectionString.

The solution I found is to use EntityConnectionStringBuilder class.

Here is the method used to create the connection:

public static EntityConnection Create(string connectionName, Type objectContextType)
{
    if (string.IsNullOrEmpty(connectionName))
        throw new ArgumentNullException("connectionName");

    ConnectionStringSettings csSettings = null;

    if ((csSettings = ConfigurationManager.ConnectionStrings[connectionName]) == null)
        throw new ArgumentException("connectionName could not be found");

    EntityConnectionStringBuilder connBuilder = new EntityConnectionStringBuilder();
    connBuilder.ProviderConnectionString = csSettings.ConnectionString;
    connBuilder.Provider = csSettings.ProviderName;

    connBuilder.Metadata = string.Format("res://{0}/", objectContextType == null ? "*" : Assembly.GetAssembly(objectContextType).FullName);

    return new EntityConnection(connBuilder.ToString());
}
The method takes 2 parameters: connectionName and objectContextType.
  • connectionName: the name of the connection from App.config or Web.config
  • objectContextType: is the type of entity container. It is used to point metadata to the assembly that contains metadata artifacts (CSDL, MSL, SSDL). If it is null it will tell Entity Framework to search all referenced assemblies to locate metadata artifacts.

This will work only if metadata artifacts is set to Embeded in Output Assembly.