Archive for the 'C#' Category

Quiz – Byte iteration in C#

At some job interviews you will be asked to explain a small piece of code, so I thought it could be fun to post some on my blog. If anyone has other examples, please let me know.

Question

How many times will Console.Write() be called ?

1
2
3
4
for (byte i = byte.MinValue; i <= byte.MaxValue; i++)  
{
	Console.Write(i);
}

A little tip
Information about Byte Structure

Implementing some useful Enumerable Extension methods from Ruby

I don’t know much about Ruby, but I am huge fan of PrototypeJS and therefore I decided to implement some of the Enumerable methods that are found within that framework (which actually comes from Ruby).

I have made two extension classes; one is called EnumerableExtension and the other ArrayExtension. I have submitted the enum extension to the MvcContrib Project, but for some reason it seems like I have forgotten the array extension, so it might get submitted later on.

The PrototypeJS Api has some great examples on how these methods work, so if you want to learn more about them, then you should check that out.

I hope that you will find them useful.

The Enumerable Extensions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
public static class EnumerableExtension
{
    /// <summary>
    /// Returns all the elements that match the filter.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public static IEnumerable<TEnumerable> GRep<TEnumerable>(this IEnumerable<TEnumerable> enumerable, string filter)
    {
        var regex = new Regex(filter);
 
        foreach (TEnumerable item in enumerable)
        {
            if (regex.IsMatch(item.ToString()))
            {
                yield return (item);
            }
        }
    }
 
    /// <summary>
    /// Returns the results of applying the iterator to each element.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <typeparam name="T2"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="func"></param>
    /// <returns></returns>
    public static IEnumerable<T2> Map<TEnumerable, T2>(this IEnumerable<TEnumerable> enumerable, Func<TEnumerable, T2> func)
    {
        foreach (TEnumerable item in enumerable)
        {
            yield return func(item);
        }
    }
 
    /// <summary>
    /// Returns all the elements for which the iterator returned false.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="match"></param>
    /// <returns></returns>
    public static IEnumerable<T> Reject<T>(this IEnumerable<T> enumerable, Predicate<T> match)
    {
        foreach (T item in enumerable)
        {
            if (!match(item))
            {
                yield return item;
            }
        }
    }
 
    /// <summary>
    /// Incrementally builds a result value based on the successive results of the iterator. This can be used for array construction, numerical sums/averages, etc.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <typeparam name="TMemo"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="accumulator"></param>
    /// <param name="func"></param>
    /// <returns></returns>
    public static TMemo Inject<TEnumerable, TMemo>(this IEnumerable<TEnumerable> enumerable, TMemo accumulator, Func<TMemo, TEnumerable, TMemo> func)
    {
        enumerable.Each(item => accumulator = func(accumulator, item));
 
        return accumulator;
    }
 
    /// <summary>
    /// Incrementally builds a result value based on the successive results of the iterator. This can be used for array construction, numerical sums/averages, etc.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <typeparam name="TMemo"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="accumulator"></param>
    /// <param name="func"></param>
    /// <returns></returns>
    public static TMemo Inject<TEnumerable, TMemo>(this IEnumerable<TEnumerable> enumerable, TMemo accumulator, Func<TMemo, TEnumerable, int, TMemo> func)
    {
        enumerable.Each((item, index) => accumulator = func(accumulator, item, index));
 
        return accumulator;
    }
 
    /// <summary>
    /// It lets you iterate over all the elements in a generic fashion, then returns the Enumerable, thereby allowing chain-calling.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="iterator"></param>
    public static void Each<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> iterator)
    {
        for(var i = 0; i < enumerable.Count(); i++)
        {
            iterator(enumerable.ToArray()[i]);
        }
    }
 
 
    /// <summary>
    /// It lets you iterate over all the elements in a generic fashion, then returns the Enumerable, thereby allowing chain-calling.
    /// </summary>
    /// <typeparam name="TEnumerable"></typeparam>
    /// <param name="enumerable"></param>
    /// <param name="iterator"></param>
    public static void Each<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable, int> iterator)
    {
        for (var index = 0; index < enumerable.Count(); index++)
        {
            iterator(enumerable.ToArray()[index], index);
        }
    }
 
    public static string ToJSON<T>(this IEnumerable<T> enumerable)
    {
        var serializer = new JavaScriptSerializer();
        return serializer.Serialize(enumerable);
    }
}

The Array Extension

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static class ArrayExtension
{
    /// <summary>
    /// Produces a new version of the array that does not contain any of the specified values.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="array"></param>
    /// <param name="values"></param>
    /// <returns></returns>
    public static T[] Without<T>(this T[] array, params T[] values)
    {
        return array.Reject(t => values.Contains(t)).ToArray();
    }
}

Further Reading

More about the keyword Yield

Extension Methods

How to serve the same data in Json, Xml or Html with Asp.Net Mvc revised

After I had blogged about my first example I talked with Eric Hexter (from the mvccontrib team) and Christian Dalager. Christian pointed out that there is an issue with the paths that doesn’t act in the same way as it does in Rails.

FormatController did something like this, when handling parameters, “/home/view.xml/4” when it should have done “/home/view/4.xml”.

Another thing that also needed to change was the requirement to inherit from the base class before it would work.

Now you can decorate your controller or action with an attribute that will handle how your data will be rendered. It is also possible to disallow one or more of the formats.

I have of course submitted it to MvcContrib, but I don’t know if it will or when it will make it into the project. So, I hope that someone can benefit from my post in the meantime.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class FormatFilterAttribute : FilterAttribute, IActionFilter
{
    /// <summary>
    /// The type of files we can server the requested content in
    /// </summary>
    private enum FileFormat { Html, Json, Xml }
 
    public FormatFilterAttribute()
    {
        Disallow = string.Empty;
        RequestedFormat = FileFormat.Html;
    }
 
    /// <summary>
    /// Formats to disallow can be either Html, Json or Xml. Use comma to seperate multiple formats.
    /// </summary>
    public string Disallow { get; set; }
 
    /// <summary>
    /// The format that has been requested
    /// </summary>
    private FileFormat RequestedFormat { get; set; }
 
    /// <summary>
    /// Occurs before an action is executed
    /// </summary>
    /// <param name="filterContext"></param>
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        FileFormat format = GetFileFormat(filterContext.HttpContext.Request.Path);
        if(IsDisallowed(format))
        {
            throw new ArgumentException("Requested format has been disallowed");
        }
 
        RequestedFormat = format;
    }
 
    /// <summary>
    /// Occurs after an action is executed
    /// </summary>
    /// <param name="filterContext"></param>
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if(!(filterContext.Result is ViewResult))
        {
            throw new InvalidOperationException("You need to call the View method, when the FormatFilter attribute is applied");
        }
 
        var view = (ViewResult)(filterContext.Result);            
        filterContext.Result = FormatViewResult(view);
    }
 
    /// <summary>
    /// Verifies if the format has been disallowed
    /// </summary>
    /// <param name="format"></param>
    /// <returns></returns>
    private bool IsDisallowed(FileFormat format)
    {
        return Disallow.Split(',').Any(s => s.ToLower() == format.ToString().ToLower());
    }
 
    /// <summary>
    /// Verifies that the requested format is one that can be servered
    /// </summary>
    /// <param name="ext"></param>
    /// <returns></returns>
    private bool IsValidFileExtension(string ext)
    {
        return Enum.GetNames(typeof(FileFormat)).Any(format => format.ToLower() == ext.Substring(1).ToLower());
    }
 
    /// <summary>
    /// 
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    private FileFormat GetFileFormat(string path)
    {
        string ext = Path.GetExtension(path);
        if(string.IsNullOrEmpty(ext))
        {
            return FileFormat.Html;
        }
 
        if (!IsValidFileExtension(ext))
        {
            throw new FormatException("Requested format is not available");
        }
 
        return (FileFormat)Enum.Parse(typeof(FileFormat), ext.Substring(1), true);
    }
 
    private ActionResult FormatViewResult(ViewResultBase view)
    {
        switch (RequestedFormat)
        {
            case FileFormat.Html:
                return view;
            case FileFormat.Json:
                return new JsonResult { Data = view.ViewData.Model };
            case FileFormat.Xml:
                return new XmlResult(view.ViewData.Model);
            default:
                throw new FormatException(string.Concat("Cannot server the content in the request format: ", RequestedFormat));
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[FormatFilter]
public class HomeController : Controller
{      
    public ActionResult Index()
    {
        var pizzas = new[]
                         {
                             new Pizza {Number = 1, Name = "Pizza 1", Price = "$10"},
                             new Pizza {Number = 2, Name = "Pizza 2", Price = "$13"},
                             new Pizza {Number = 3, Name = "Pizza 3", Price = "$20"}
                         };
 
        return View(pizzas);
    }
}

Working with parameters

If you are going send data, like an ID, to your Action then you need to add an extra route or else it might not get parse correctly.

1
2
3
4
5
6
// Add this to Global.asax
routes.MapRoute(
	"Format",
	""{controller}/{action}/{id}.{format}"",
	new {id = "", format = ""}
);

Next Page »