Monday, December 5, 2011

Create custom config section handler

In order to create a custom config section handler we would use the following namespaces:

System.Configuration
System.Collections
System.Collections.Generic
System.Collections.Specialized

Now a sample xml for which we intend to create a config section handler:

<TransformerConfigurationSection MaxSlotsPerMachine="5">
    <!-- Remote Service Machines-->
    <servicemachine id="01">
      <Id value="1" />
      <Name value="server1" />     
    </servicemachine>
    <servicemachine id="02">
      <Id value="2" />
      <Name value="server2" />
    </servicemachine>
</TransformerConfigurationSection>

Now first we create a ConfigurationSection Class that reads this section from a config file. The code looks as follows:


public class TransformerConfigurationSection : ConfigurationSection 
{
    // 1. MaxSlotsPerMachine -- attribute
    // 2. serviceMachine -- Element collection
 
    public const string SectionXPath = "TransformerConfigurationSection";
    public TransformerConfigurationSection()
    {
        Properties.Add(new ConfigurationProperty("MaxSlotsPerMachine", typeof(string), null));
    }
 
    public static TransformerConfigurationSection GetSection()
    {
        return (TransformerConfigurationSection)ConfigurationManager.GetSection(SectionXPath);
    }
 
    [ConfigurationProperty("MaxSlotsPerMachine")]
    public string MaxSlotsPerMachine
    {
        get
        {
            return (string)this["MaxSlotsPerMachine"];
        }
    }
 
    [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
    public MachineElementCollection ServiceMachines
    {
        get
        {
            return (MachineElementCollection)this[""];
        }
    }
}

Now we create the class MachineElementCollection that represents a ConfigurationElementCollection.

public class MachineElementCollection : MachineConfigurationElementCollection<ServiceMachineElement>
{
    public MachineElementCollection()
        :base("servicemachine")
    {  
    }
 
    protected override object  GetElementKey(ConfigurationElement element)
    {
        return ((ServiceMachineElement) element).Id;
    }
}
Now create a base class that allows you to reuse the ConfigurationElementCollection to be of any type.

public abstract class MachineConfigurationElementCollection<T> : ConfigurationElementCollection where T: ConfigurationElement, new()
{
    private ConfigurationElementCollectionType collectionType;
    private string elementName;
    public override ConfigurationElementCollectionType  CollectionType
    {
        get 
        { 
                return collectionType;
        }
    }
 
    protected override string  ElementName
    {
        get
        {
            return String.IsNullOrEmpty(elementName) ? base.ElementName : elementName;
        }
    }
 
    public virtual T this[object key]
    {
        get
        {
            var configurationElementType = (T)BaseGet(key);
            return (object)configurationElementType != null ? configurationElementType : null;
        }
        set
        {
            if (IsReadOnly())
                Add(value);
            if (GetElementKey(value).ToString().Equals((string)key, StringComparison.Ordinal))
            {
                if (BaseGet(key) != null)
                    BaseRemove(key);
                Add(value);
            }
        }
    }
 
    public T this[int index]
    {
        get
        {
            return (T)BaseGet(index);
        }
        set
        {
            if (!IsReadOnly() && !ThrowOnDuplicate && BaseGet(index) != null)
                BaseRemoveAt(index);
            BaseAdd(index, value);
        }
    }
 
    internal MachineConfigurationElementCollection()
        : this(ConfigurationElementCollectionType.AddRemoveClearMap, null)
    {
    }
 
    internal MachineConfigurationElementCollection(string elementname)
        : this(ConfigurationElementCollectionType.AddRemoveClearMap, elementname)
    {
    }
 
    internal MachineConfigurationElementCollection(ConfigurationElementCollectionType collectionType, string elementName)
    {
        this.collectionType = collectionType;
        this.elementName = elementName;
        if (string.IsNullOrEmpty(elementName))
            return;
        AddElementName = elementName;
    }
 
    internal MachineConfigurationElementCollection(ConfigurationElementCollectionType collectionType, string elementName, IComparer comparer)
        : base(comparer)
    {
        this.collectionType = collectionType;
        this.elementName = elementName;
    }
 
    protected override void BaseAdd(ConfigurationElement element)
    {
      if (!IsReadOnly() && !ThrowOnDuplicate)
      {
        object elementKey = this.GetElementKey(element);
        if (ContainsKey(elementKey))
          BaseRemove(elementKey);
      }
 
      base.BaseAdd(element);
    }
 
    public void Add(T element)
    { 
      BaseAdd(element);
    }
 
    public void Clear()
    {
      BaseClear();
    }
 
    public virtual bool ContainsKey(object key)
    {
      if (key != null)
        return null != BaseGet(key);
      var list = new List<string>();
 
      foreach (PropertyInformation propertyInformation in (NameObjectCollectionBase) CreateNewElement().ElementInformation.Properties)
      {
        if (propertyInformation.IsKey)
          list.Add(propertyInformation.Name);
      }
        return false;
    }
 
    protected override ConfigurationElement CreateNewElement()
    {
      return Activator.CreateInstance<T>();
    }
}
Now since the ConfigurationElementCollection has been created now we create the actual ConfigurationElement.

public class ServiceMachineElement : ConfigurationElement
{
    public ServiceMachineElement()
    {
        Properties.Add(new ConfigurationProperty(ServiceMachineIdKey, typeof(string), ""));
        Properties.Add(new ConfigurationProperty(IdKey, typeof(IdElement), null));
        Properties.Add(new ConfigurationProperty(NameKey, typeof(NameElement), null));
    }
 
    private const string ServiceMachineIdKey = "id";
    [ConfigurationProperty(ServiceMachineIdKey, IsRequired = false)]
    public string ServiceMachineId
    {
        get { return (String)this[ServiceMachineIdKey]; }
        set { this[ServiceMachineIdKey] = value; }
    }    
 
    private const string IdKey = "Id";
    [ConfigurationProperty(IdKey, IsRequired = true)]
    public IdElement Id
    {
        get { return (IdElement)this[IdKey]; }
        set { this[IdKey] = value; }
    }
 
    private const string NameKey = "Name";
    [ConfigurationProperty(NameKey, IsRequired = true)]
    public NameElement Name
    {
        get { return (NameElement)this[NameKey]; }
        set { this[NameKey] = value; }
    }    
}
Since, we have the servicemachine element with child elements of type NameElement and IdElement we create these classes.

public class IdElement : ConfigurationElement
{
    public IdElement()
    {
        Properties.Add(new ConfigurationProperty(ValueKey, typeof(string), null));
    }
 
    private const string ValueKey = "value";
    [ConfigurationProperty(ValueKey, IsRequired = true)]
    public string Value
    {
        get { return (string)this[ValueKey]; }
        set { this[ValueKey] = value; }
    }
}

public class NameElement : ConfigurationElement
    {
        public NameElement()
        {
            Properties.Add(new ConfigurationProperty(ValueKey, typeof(string), null));
        }
 
        private const string ValueKey = "value";
 
        [ConfigurationProperty(ValueKey, IsRequired = true)]
        public string Value
        {
            get { return (string)this[ValueKey]; }
            set { this[ValueKey] = value; }
        }
    }

That is it. The config section reader is done. Now just add the above xml to your app.config or web.config and define the configsection as shown below:

<configuration>
  <configSections>
    <section name="TransformerConfigurationSection" type="Sample.TransformerConfigurationSection, Sample"/>
  </configSections>
</configuration>

Tuesday, November 29, 2011

How to cancel a Parallel.For or Parallel.ForEach loop

We can cancel the Parallel.For or Parallel.ForEach using a CancellationToken as shown below:

namespace CancelParallelLoops
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    class Program
    {
        public static void Main()
        {
            int[] nums = Enumerable.Range(0, 10000000).ToArray();
            CancellationTokenSource cts = new CancellationTokenSource();
 
           // Use ParallelOptions instance to store the CancellationToken
            ParallelOptions po = new ParallelOptions();
            po.CancellationToken = cts.Token;
            po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
 
            Console.WriteLine("Press any key to start. Press 'c' to cancel.");
            Console.ReadKey();            
 
            // Run a task so that we can cancel from another thread.
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
 
                Console.WriteLine("press any key to exit");
            });
 
            try
            {
                Parallel.ForEach(nums, po, (num) =>
                {
                    double d = Math.Sqrt(num);
                    Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
                    po.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }
 
            Console.ReadKey();
        }
    }
}

How to use DataBinding with DataServiceCollections?

The following link explains on how to perform data binding with DataServiceCollections.

Data Binding with DataServiceCollections

Tuesday, November 22, 2011

Xml Viewer in WinForms application

We can create a XmlViewer using a WPF user control and use it in our windows forms application.

Create a new class library project and add a WPF user control called XmlViewer


<UserControl x:Class="Viewer.XmlViewer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:xmlstack="clr-namespace:System.Xml;assembly=System.Xml"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <SolidColorBrush Color="Blue" x:Key="xmlValueBrush"/>
        <SolidColorBrush Color="Red" x:Key="xmAttributeBrush"/>
        <SolidColorBrush Color="DarkMagenta" x:Key="xmlTagBrush"/>
        <SolidColorBrush Color="Blue" x:Key="xmlMarkBrush"/>
        <DataTemplate x:Key="attributeTemplate">
            <StackPanel Orientation="Horizontal"                        Margin="3,0,0,0" HorizontalAlignment="Center">
                <TextBlock Text="{Binding Path=Name}" 
                           Foreground="{StaticResource xmAttributeBrush}"/>
                <TextBlock Text="=&quot;" 
                           Foreground="{StaticResource xmlMarkBrush}"/>
                <TextBlock Text="{Binding Path=Value}" 
                           Foreground="{StaticResource xmlValueBrush}"/>
                <TextBlock Text="&quot;" 
                           Foreground="{StaticResource xmlMarkBrush}"/>
            </StackPanel>
        </DataTemplate>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>
        <HierarchicalDataTemplate x:Key="treeViewTemplate" 
                                  ItemsSource="{Binding XPath=child::node()}">
            <StackPanel Orientation="Horizontal" Margin="3,0,0,0" 
                        HorizontalAlignment="Center">
                <TextBlock Text="&lt;" HorizontalAlignment="Center" 
                           Foreground="{StaticResource xmlMarkBrush}" 
                           x:Name="startTag"/>
                <TextBlock Text="{Binding Path=Name}"
                    Margin="0"
                    HorizontalAlignment="Center"
                    x:Name="xmlTag"
                    Foreground="{StaticResource xmlTagBrush}"/>
                <ItemsControl
                    ItemTemplate="{StaticResource attributeTemplate}"
                    ItemsSource="{Binding Path=Attributes}"
                    HorizontalAlignment="Center">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
                <TextBlock Text="&gt;" HorizontalAlignment="Center" 
                           Foreground="{StaticResource xmlMarkBrush}" 
                           x:Name="endTag"/>
            </StackPanel>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding NodeType}">
                    <DataTrigger.Value>
                        <xmlstack:XmlNodeType>Text</xmlstack:XmlNodeType>
                    </DataTrigger.Value>
                    <Setter Property="Text" Value="{Binding InnerText}" 
                            TargetName="xmlTag"/>
                    <Setter Property="Foreground" Value="Blue" 
                            TargetName="xmlTag"/>
                    <Setter Property="Visibility" Value="Collapsed" 
                            TargetName="startTag"/>
                    <Setter Property="Visibility" Value="Collapsed" 
                            TargetName="endTag"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding HasChildNodes}" Value="False">
                    <Setter Property="Text" Value="/&gt;" TargetName="endTag"/>
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </UserControl.Resources>
    <Grid>
        <TreeView Grid.Row="2" Grid.ColumnSpan="2" Name="xmlTree" 
                  ItemTemplate="{StaticResource treeViewTemplate}"/>
    </Grid>
</UserControl>

The code behind for the above user control as shown below:


public partial class XmlViewer : UserControl
{
    private XmlDocument xmldocument;
    public XmlViewer()
    {
        InitializeComponent();
    }
 
    public XmlDocument XmlDocument
    {
        get { return xmldocument; }
        set
        {
            xmldocument = value;
            BindXmlDocument();
        }
    }
 
    private void BindXmlDocument()
    {
        if (xmldocument == null)
        {
            xmlTree.ItemsSource = null;
            return;
        }
 
        var provider = new XmlDataProvider {Document = xmldocument};
        var binding = new Binding {Source = provider, XPath = "child::node()"};
        xmlTree.SetBinding(ItemsControl.ItemsSourceProperty, binding);
    }
}

Once you are done with the above things now build the project. Now create a new Windows Forms project and add a reference of this Dll. Now open a form and add a WPF Interoperability control called ElementHost. Once you add this then you can see in the select hosted content dropdown the XmlViewer control. If you dont find it just try building your project once and it should come up. Now in the code behind of your forms control do the following:

private void btnBrowse_Click(object sender, EventArgs e)
        {
                XmlDocument XMLdoc = new XmlDocument();
                try
                {
                    XMLdoc.Load(@"C:\Sample.xml");
                }
                catch (XmlException)
                {
                    MessageBox.Show("The XML file is invalid");
                    return;
                }
                ((XmlViewer) wpfElementHost.Child).XmlDocument = XMLdoc;
        }

How to implement a binary tree in C# using Generics

We can implement a binary tree in C# using generics as shown here.

Tuesday, November 15, 2011

Quick start with Moq framework

The below article gives a quick start with Moq framework to use when unit testing.

Moq - Quick start

Tuesday, November 8, 2011

Support for large URL's

We might encounter scenarios where the URL that we need to have is very large when developing applications. In such cases we need to do the below configurations in order to have large URL's:

In the web.config set the following:


<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime  maxUrlLength="2048" maxQueryStringLength="2048" maxRequestLength="2048" />
  </system.web>

Then find the registry setting for a URLSegmentLength and increase it to some value appropriate:

UrlSegmentMaxLength registry setting, increasing to 2048 (x800)

If the service is being hosted in IIS then also add the following to the webServer section in web.config:

<system.webServer>
      <security>
         <requestFiltering>
            <requestLimits maxUrl="a large value"/>              
         </requestFiltering>
      </security>
   </system.webServer>
 

That should be enough for you to have your URL's to be very large.