Archive

Posts Tagged ‘VS 2008’

Covariance in C#

February 28, 2011 1 comment

We are going to have a quick look at covariance in C#.

Only elements that can be covariant:

  • Interfaces
  • Delegates

Convariance is similar to Inheritance in the sense that if you have a class like IEnumerable which is covariant then you can assign a subclass of IEnumerable to IEnumerable.

Example: Base Person, Sub Class is Student. With Covariance you can assign IEnumerable to IEnumerable

You would just naturally think this would work but is has not until .NET 4 was introduced.

To allow convariance you must mark the generic parameter as out T as shown below in IIterable and IIterator. I wrote my own iterator design pattern based classes below to illustrate this.

you can only assign using references as shown in the main method. Assigning to base classes not interfaces won’t work.

using System;
using System.Collections.Generic;

namespace Variance
{


    public abstract class Entity<TKey> : IEquatable<Entity<TKey>>
    {

        public TKey Id { get; set; }

        protected Entity()
        {
            Id = default(TKey);
        }

        protected Entity(TKey identity)
        {
            Id = identity;
        }

        public override bool Equals(object obj)
        {
            var entity = obj as Entity<TKey>;
            return Equals(entity);
        }

        public bool Equals(Entity<TKey> other)
        {
            return other != null && Equals(Id, other.Id);
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
    }

    public class Person : Entity<int>
    {
        public string Name { get; set; }

        public override string ToString()
        {
            return String.Format("{0} - {1}", Id, Name);
        }
    }

    public class Student : Person
    {
        public string Course { get; set; }
    }

    public interface IIterator<out T>
    {
        bool HasMoreElements { get; }
        T Current { get; }
        void Continue();
    }

    public interface IIterable<out T>
    {
        IIterator<T> GetIterator();
    }

    public class BasicList<T> : IIterable<T>
    {

        protected List<T> Items = new List<T>();

        public void AddItem(T item)
        {
            Items.Add(item);
        }

        public IIterator<T> GetIterator()
        {
            return new BlIterator<T>(Items);
        }

        public void PrinttoConsole()
        {
            foreach (var item in Items)
            {
                Console.WriteLine(item);
            }
        }

        public class BlIterator<T> : IIterator<T>
        {

            protected List<T> items = new List<T>(); 

            public BlIterator(List<T> items)
            {
                this.items = items;
            }

            private int index;

            public bool HasMoreElements
            {
                get { return index <= items.Count - 1; }
            }

            public T Current
            {
                get { return items[index]; }
            }

            public void Continue()
            {
                index++;
            }
        }


    }

    class Program
    {

        

        static void Main()
        {

            IIterable<Student> students = GetStudents();

            Print(students); // Covariance



            IIterable<Person> people = students; // Covariance

            Print(people);

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        public static IIterable<Student> GetStudents()
        {
            BasicList<Student> students = new BasicList<Student>();
            students.AddItem(new Student { Id = 1, Name = "Blair" });
            students.AddItem(new Student { Id = 2, Name = "Tim" });
            students.AddItem(new Student { Id = 3, Name = "Tom" });
            return students;
        }

        public static void Print(IIterable<Person> print) // Covariance
        {

            var iterator = print.GetIterator();

            while (iterator.HasMoreElements)
            {
                Console.WriteLine(iterator.Current);
                iterator.Continue();
            }
        }
    }
}

Blair…

Redirect to a safe location Error Action Filter in ASP.NET MVC

February 15, 2011 Leave a comment

I have an example of an error action filter on how you can move the user to a previously know safe location in mvc with the following action filter. I and an error to tempdata which you could look for in the site master to show the error.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace Learning.ActionFilters
{
    public class RedirectToRouteErrorAttribute : FilterAttribute, IExceptionFilter
    {
        public IEnumerable<string> RouteValues { get; private set; }
        public string ErrorMessage { get; private set; }

        public RedirectToRouteErrorAttribute(string errormessage, params string[] tokens)
        {
            ErrorMessage = errormessage;
            RouteValues = tokens;
        }

        public void OnException(ExceptionContext filterContext)
        {
            if (filterContext.ExceptionHandled)
                return;

            var items = from route in filterContext.RouteData.Values
                        join key in RouteValues on route.Key equals key
                        select route;

            var dict = new RouteValueDictionary(items);

            filterContext.Controller.TempData.Add("errormessage", ErrorMessage);
            filterContext.Result = new RedirectToRouteResult(dict);
            filterContext.HttpContext.Response.Clear();
            filterContext.ExceptionHandled = true;
        }
    }
}

// Here is an example of the usage
 [HttpPut]
 [ActionName("Edit")]
 [RedirectToRouteErrorAttribute("controller","action","id")]
 public virtual ActionResult EditUser(){}

You just specify which route values you want to keep so the RedirectToRouteResult work as required

Blair…

Creating MVC Controller Factories with Windsor

December 14, 2010 Leave a comment

You can setup dependency injection just by implementing the IControllerFactory interface or inheriting from DefaultControllerFactory. Default controller factory is preferred as it takes care of providing you more than just a controller name like Customer. Doing this manually is not great as you can see from the example below.

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using System.Linq;

namespace MVCSamples.Infrastructure
{
    public class WindsorControllerFactory : IControllerFactory
    {

        private IEnumerable<Type> _controllerTypes;

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            BuildDefaultControllerTypes();
            return IoC.Resolve(GetTypeNameForController(controllerName)) as IController;
        }

        public void BuildDefaultControllerTypes()
        {
            if (_controllerTypes == null || !_controllerTypes.Any())
                _controllerTypes = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.Name.EndsWith("Controller")).ToList();
        }

        public string GetTypeNameForController(string controllername)
        {
            return _controllerTypes.First(x => x.Name == String.Format("{0}Controller", controllername)).FullName;
        }

        public void ReleaseController(IController controller)
        {
            var disposablecontroller = controller as IDisposable;
            if (disposablecontroller != null) disposablecontroller.Dispose();
            IoC.Release(controller);
        }
    }
}

The second implementation below is not so naive. The DefaultControllerFactory takes care of finding the controller type for you. Just override the GetControllerInstance Method.

using System;
using System.Web.Mvc;

namespace MVCSamples.Infrastructure
{
    public class WindsorControllerFactory : DefaultControllerFactory
    {

        protected override IController GetControllerInstance(Type controllerType)
        {
            return IoC.Resolve(controllerType) as IController;
        }

        public override void ReleaseController(IController controller)
        {
            var disposablecontroller = controller as IDisposable;
            if (disposablecontroller != null) disposablecontroller.Dispose();
            IoC.Release(controller);
        }
    }
}

Blair

Basic Thread Coordination Part 1

November 23, 2010 Leave a comment

When threads are created they run interdependently from the thread that created them. This is exactly what we want. However we often need to wait for multiple threads doing work to finish before continuing. This is done with the Join() method on the thread which blocks the main thread while waiting till the thread completes.

using System;
using System.Threading;

namespace ThreadsAreForScheduling
{

    public static class ThreadExtensions
    {
        public static void JoinAll(params Thread[] threads)
        {
            Array.ForEach(threads, thread => thread.Join());
        }

        public static void JoinAll(TimeSpan timeout, params Thread[] threads)
        {
            Array.ForEach(threads, thread => thread.Join(timeout));
        }
    }

    public class Program
    {
        public static void Main()
        {

            Program p = new Program();
            p.CreatingThreadsToToRunCalculations();

            Console.WriteLine("Press any key to quit...");
            Console.ReadKey();
        }

        public void CreatingThreadsToToRunCalculations()
        {
            Thread t1 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^1: {0}", CalculatePower(10, 1));
            });
            Thread t2 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^2: {0}", CalculatePower(10, 2));
            });
            Thread t3 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^3: {0}", CalculatePower(10, 3));
            });
            Thread t4 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^4: {0}", CalculatePower(10, 4));
            });

            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();

            ThreadExtensions.JoinAll(t1, t2, t3, t4);
            
            // The above is equivalent to
            // t1.Join();
            // t2.Join();
            // t3.Join();
            // t4.Join();

        }

        private int CalculatePower(int a, int power)
        {
            if (power == 1) return 10;
            int value = 10;

            for (var i = 1; i < power; i++)
            {
                value *= 10;
            }
            return value;
        }
    }
}

Blair

Threads To Schedule Work

November 22, 2010 Leave a comment
using System;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Threading;

namespace ThreadsAreForScheduling
{
    class Program
    {
        public static void Main()
        {

            Program p = new Program();
            p.CreatingThreadsToToRunCalculations();

            Console.WriteLine("Press any key to quit...");
            Console.ReadKey();
        }

        public void CreatingThreadsToToRunCalculations()
        {
            Thread t1 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^1: {0}", CalculatePower(10, 1));
            });
            Thread t2 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^2: {0}", CalculatePower(10, 2));
            });
            Thread t3 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^3: {0}", CalculatePower(10, 3));
            });
            Thread t4 = new Thread(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("10^4: {0}", CalculatePower(10, 4));
            });

            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();

        }

        
        private int CalculatePower(int a, int power)
        {

            if (power == 1) return 10;

            int value = 10;

            for (var i = 1; i < power; i++)
            {
                value *= 10;
            }

            return value;
        }
    }
}

Note this is not recommended. You should use Tasks or the ThreadPool as threads are a means of scheduling and are expensive.

Blair…

Handling Causality with APM and Not ThreadPool QueueUserWorkItem

November 17, 2010 Leave a comment
using System;
using System.Runtime.Remoting.Messaging;

namespace AsynchronousProgrammingModelSamples
{

    public class ApmAsychExecution
    {
        public void ExecuteAsynchronouslyWithCallback<TResult>(Func<TResult> function, Action<TResult> callback,
                                                              Action<Exception> exception)
        {
            TResult result = default(TResult);

            Action action = () =>
                                {
                                    result = function();
                                };

            action.BeginInvoke(fn =>
                                  {

                                      try
                                      {
                                          AsyncResult aresult = (AsyncResult) fn;
                                          Action caller = (Action) aresult.AsyncDelegate;
                                          caller.EndInvoke(aresult);
                                          callback(result);
                                      }catch(Exception e)
                                      {
                                          exception(e);
                                      }
                                  }, null);

        }

        public void ExecuteAsynchronouslyWithCallback<TArg, TResult>(Func<TArg,TResult> function, Action<TResult> callback,
                                                              Action<Exception> exception, TArg argument)
        {
            TResult result = default(TResult);

            Action action = () =>
            {
                result = function(argument);
            };

            action.BeginInvoke(fn =>
            {

                try
                {
                    AsyncResult aresult = (AsyncResult)fn;
                    Action caller = (Action)aresult.AsyncDelegate;
                    caller.EndInvoke(aresult);
                    callback(result);
                }
                catch (Exception e)
                {
                    exception(e);
                }
            }, null);

        }
    }

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public override string ToString()
        {
            return String.Format("Id: {0}, Name: {1}", Id, Name);
        }
    }

    public class Program
    {
        public static void Main()
        {
            Program p = new Program();
            p.ExecuteItemAsyncronously();

            Console.WriteLine("Press any key to quit..");
            Console.ReadKey();
        }

        public void ExecuteItemAsyncronously()
        {
            ApmAsychExecution apm = new ApmAsychExecution();
            apm.ExecuteAsynchronouslyWithCallback(
                    () => new Customer { Id = 1, Name = "Blair Davidson" }, Console.WriteLine, Console.WriteLine
                );
            apm.ExecuteAsynchronouslyWithCallback(
                    name => new Customer { Id = 1, Name = name }, Console.WriteLine, Console.WriteLine, "Patrick Smith"
                );
            apm.ExecuteAsynchronouslyWithCallback(
                    () =>
                        {
                            throw new InvalidOperationException("Error Testing....");
                            return new Customer {Id = 1, Name = "Blair Davidson"};
                        }, Console.WriteLine, Console.WriteLine
                );
        }
    }
}

APM Techniques with FileStream

November 17, 2010 Leave a comment
using System;
using System.IO;
using System.Linq;
using System.Text;

namespace AsynchronousProgrammingModelSamples
{
    public class Program
    {
        private string path = @"C:\test.txt";

        static void Main()
        {
            Program p = new Program();
            p.WriteContentsToFile();
           // p.ProcessLinesWithAPMUsingBlockWait();
           // p.ProcessLinesWithAPMUsingPolling();
            p.ProcessLinesWithAPMUsingCallbacks();
            Console.WriteLine("Press any key to quit..");
            Console.ReadKey();
        }

        public void ProcessLinesWithAPMUsingCallbacks()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
                data = new byte[stream.Length];
                stream.BeginRead(data, 0, data.Length, x =>
                                                           {
                                                               Console.WriteLine(Encoding.ASCII.GetString(data));
                                                           }, null);
            }
            catch (Exception e)
            {

            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }

        public void ProcessLinesWithAPMUsingPolling()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
                data = new byte[stream.Length];
                IAsyncResult result = stream.BeginRead(data, 0, data.Length, null, null);

                while(!result.IsCompleted) // Pool and do something - Not a great way to do things 🙂
                {
                    Console.WriteLine("Waiting ....");
                }


                stream.EndRead(result);

                Console.WriteLine(Encoding.ASCII.GetString(data));

            }
            catch (Exception e)
            {

            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }

        public void ProcessLinesWithAPMUsingBlockWait()
        {
            FileStream stream = null;
            byte[] data = null;
            try
            {
                stream = new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.Read,1024,FileOptions.Asynchronous);
                data = new byte[stream.Length];
                IAsyncResult result = stream.BeginRead(data, 0, data.Length, null, null);

                stream.EndRead(result); // Basically we are blocking here util finished so no difference to the synch
                                        // version

                Console.WriteLine(Encoding.ASCII.GetString(data));

            }
            catch (Exception e)
            {

            }
            finally
            {
                if(stream != null) stream.Close();
            }
        }

        public void WriteContentsToFile()
        {
            var items = Enumerable.Range(1, 1000)
                                  .Select(x => x.ToString())
                                  .ToArray();

            var text = String.Join(Environment.NewLine, items);
            File.WriteAllText(path, text);

        }
    }
}

Blair…