Posts tagged ‘.Net 3.5’

C#: ToString To Report all Properties Even Private Ones Via Reflection

At some point one needs to view all the properties of an instance outside of a debugger such as for a unit test reporting the results or possibly a console application informing its status to the output. To achieve the results one overrides `ToString()` and by hand writes the information of the instance’s properties and their values to the output string. This can become cumbersome if the class instance is changing or when one realizes that the time ratio of creating such a reporting operation verses the size of what is being reported can lead to valuable time taken away from the developer.

This article demonstrates a C# extension which will take any class instance and report any non null properties as well as any string lists. The goal of the report is to provide information on the standard properties (string, int, datetime, etc) as well as string lists and ignores any  complex objects. Also provided is the ability to show the non-public properties.

For the resulting visual list, the code lines up the output report in key value pairs where the largest character count key name (the property name reported) will be spaced out along with all other names.

Here is an example result of a class instance with differing properties. Note that `MemberOfAsList` is a List<string> property which internally splits out the property `MemberOf` string (by its comma) into a list. This extension shows the list as a `string__abENT__#46;join` of `__abENT__quot;, __abENT__quot;`.

DistinguishedName : CN=Write Frank,OU=Test,OU=Acme Industries,DC=amce-co,DC=acme,DC=net
CommonName        : Write Frank Lloyd
MemberOf          : CN=2042_Identity,CN=UserIdentities,CN=AlphaVision,DC=acme-co,DC=acme,DC=net
MemberOfAsList    : CN=2042_Identity, CN=UserIdentities, CN=AlphaVision, DC=acme-co, DC=acme, DC=net
otherTelephone    : 303-555-555
Name              : Wright Frank
WhenChanged       : 3/17/2014 9:04:06 PM
LogonCount        : 0

Extension Method

The following is an extension method whose goal is to reflect the type being passed in, determine the sizing of the data for output and then reports the properties each on a different line. String lists values are specified by a `,` (comma and space) separator between each value.

public static string ReportAllProperties<T>(this T instance) where T : class
{

    if (instance == null)
        return string.Empty;

    var strListType = typeof(List<string>);
    var strArrType  = typeof(string[]);

    var arrayTypes   = new[] { strListType, strArrType };
    var handledTypes = new[] { typeof(bool), typeof(Int32), typeof(String), typeof(DateTime), typeof(double), typeof(decimal), strListType, strArrType };

    var validProperties = instance.GetType()
                                  .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                  .Where(prop => handledTypes.Contains(prop.PropertyType))
                                  .Where(prop => prop.GetValue(instance, null) != null)
                                  .ToList();

    var format = string.Format("{{0,-{0}}} : {{1}}", validProperties.Max(prp => prp.Name.Length));

    return string.Join(
             Environment.NewLine,
             validProperties.Select(prop => string.Format(format, 
                                                          prop.Name,
                                                          (arrayTypes.Contains(prop.PropertyType) ? string.Join(", ", (IEnumerable<string>)prop.GetValue(instance, null))
                                                                                                  : prop.GetValue(instance, null)))));
}

Usage

public override string ToString()
{
    return ( this.ReportAllProperties() );
}

Test & Results

var test = new MyClass("Admin") { Name = "Omegaman", 
                                  ID = 1,  
                                  StartDate = DateTime.Now,
                                  AccessPoints = new List<string> { "Alpha", "Beta", "Gamma" },
                                  WeekDays = new string[]{ "Mon", "Tue" }
                                 };

 Console.WriteLine (test.ToString());

/*
Name         : Omegaman
ID           : 1
Role         : Admin
AccessPoints : Alpha, Beta, Gamma
WeekDays     : Mon, Tue
StartDate    : 3/18/2014 12:16:07 PM
*/

....

public class MyClass
{
    public string Name               { get; set; }
    public int ID                    { get; set; }
    private string Role              { get; set; }
    public List<string> AccessPoints { get; set; }
    public string[] WeekDays         { get; set; }    
    public DateTime StartDate        { get; set; }

    public MyClass(string role)
    {
        Role = role;
    }

    public override string ToString()
    {
       return ( this.ReportAllProperties() );
    }

}

Done!

Share

C# Linq: Find Missing Values in a Sequence of Numbers and Other Sequence Related lists as IEnumerable Extensions

Water bubble and wavesI recently had a need to determine if a sequence of integers was solid, not broken, and whether it contained a gap of any missing numbers to report to the end user. I researched the issue and was dismayed that the examples found on the internet seemed to have unnecessary overheads of copied arrays or other artifacts and were too cumbersome for my needs. From that I wrote these C# extensions which work for any .Net above 3.5. Below I document the extension methods to get the missing numbers of a sequence, quickly determine if a sequence is broken and finally report where the existing numbers before the break of the sequence. See the end for the whole extension class for easier copying.

Problem Definition

If one has a set of numbers say

{ 2, 4, 7, 9 }

it has a broken sequence because there are missing numbers from the set 2-9. Those missing numbers are:

{ 3, 5, 6, 8 }

Find Missing Numbers In a Sequence

This method is the one I created first. It uses the Linq Aggregate extension to enumerate over the numbers in the set. If there is a gap which is greater than 1 between the numbers (the difference below is > 0 but same concept) then it reports the numbers missing between the two.

public static IEnumerable<int> SequenceFindMissings(this IList<int> sequence)
{

    var missing = new List<int>();

    if ((sequence != null) && (sequence.Any()))
    {
        sequence.Aggregate((seed, aggr) =>
                            {
                                var diff = (aggr - seed) - 1;

                                if (diff > 0)
                                    missing.AddRange(Enumerable.Range((aggr - diff), diff));

                                return aggr;
                            });
    }

    return missing;
}

Quickly Determine Broken Sequence

Is the sequence broken from the first number to the last in the set?

public static bool IsSequenceBroken(this IEnumerable<int> sequence)
{
    bool broken = false;

    if (sequence != null) 
    {
        var sequenceAsList = sequence.ToList();

        if (sequenceAsList.Any())
        {
            int lastValue = sequence.First();

            broken = sequence.Any(value =>
                                    {
                                        if ((value - lastValue) > 1)
                                            return true;

                                        lastValue = value;

                                        return false;
                                    }); 
        }
    }

    return broken;
}

Report Last Valid Number Before The Break

This is useful in situations where one needs to report where the break happens, say the user is editing in a grid and one highlights the existing number which precedes the missing number(s).

Example here returns a 2 and 5 which are the numbers which precede the break.

   (new List() { 1, 2, 4, 5, 7, 8}).SequenceReportMissingsBreakStarts()

Here is the method:

public static IEnumerable<int> SequenceReportMissingsBreakStarts(this IList<int> sequence)
{

    var breaks = new List<int>();

    if ((sequence != null) && (sequence.Any()))
    {

        sequence.Aggregate((seed, aggr) =>
                            {
                                var diff = (aggr - seed) - 1;

                                if (diff > 0)
                                    breaks.Add(seed);
                                return aggr;
                            });
    }

    return breaks;
}

Full Extension Source With Comments

Here is the code for an easier copy

public static class SequenceExtensions
{
    /// <summary>
    /// Take a sequence of numbers and if there are any gaps greater than 1 between the numbers,
    /// report true.
    /// </summary>
    /// <param name="sequence">A set of numbers to check.</param>
    /// <returns>True if the there is a break in the sequence of numbers.</returns>
    public static bool IsSequenceBroken(this IEnumerable<int> sequence)
    {
        bool broken = false;

        if (sequence != null)
        {
            var sequenceAsList = sequence.ToList();

            if (sequenceAsList.Any())
            {
                int lastValue = sequence.First();

                broken = sequence.Any(value =>
                                        {
                                            if ((value - lastValue) > 1)
                                                return true;

                                            lastValue = value;

                                            return false;
                                        });
            }
        }

        return broken;
    }

    /// <summary>
    /// Take a sequence of numbers and report the missing numbers. Stop at first break found.
    /// </summary>
    /// <param name="sequence">Set of Numbers</param>
    /// <returns>True of sequence has missing numbers</returns>
    public static IEnumerable<int> SequenceFindMissings(this IList<int> sequence)
    {

        var missing = new List<int>();

        if ((sequence != null) && (sequence.Any()))
        {
            sequence.Aggregate((seed, aggr) =>
                                {
                                    var diff = (aggr - seed) - 1;

                                    if (diff > 0)
                                        missing.AddRange(Enumerable.Range((aggr - diff), diff));

                                    return aggr;
                                });
        }

        return missing;

    }

    /// <summary>
    /// A missing break start in a sequence is where the drop off occurs in the sequence.
    /// For example 3, 5, has a missing break start of the #3 for #4 is the missing.
    /// </summary>
    /// <param name="sequence">Set of Numbers</param>
    /// <returns>The list of break numbers which exist before the missing numbers.</returns>
    public static IEnumerable<int> SequenceReportMissingsBreakStarts(this IList<int> sequence)
    {

        var breaks = new List<int>();

        if ((sequence != null) && (sequence.Any()))
        {

            sequence.Aggregate((seed, aggr) =>
                                {
                                    var diff = (aggr - seed) - 1;

                                    if (diff > 0)
                                        breaks.Add(seed);
                                    return aggr;
                                });
        }

        return breaks;

    }
}

Hope this helps!

Share

Asp.Net C#: Upgrading Website to Latest Version Gotchas and How to Resolve

iStock_000015438998XSmallOne can get lost in the weeds when upgrading an asp.net .Net 1 website to anything from .Net 2 through .Net 4.  One of the biggest problems after the initial conversion is that when built each page or control throws a build error:

Could not load type ‘MyNamespace.myWebPage’.

The issue stems from the fact that things changed, made life easier for new projects, and namespaces which were required were removed and certain attributes changed. To resolve the above issue follow these steps presented in this article.

In the code behind file

  1. Remove the namespace scope. In the example below remove the highlighted lines:
    namespace MyNamespace
    {
        public class myWebPage : System.Web.UI.Page {}
    }
  2. Add the modifier partial to the class definition to make it look like this
    public partial class myWebPage : System.Web.UI.Page { ... }

In the aspx File

Which initially looks like this:

<%@ Page language="c#" AutoEventWireup="false"
                       Codebehind="myWebPage.aspx.cs"
                       Inherits="MyNamespace.myWebPage" %>
  1. Change the attribute Codebehind to CodeFile.
  2. Remove the namespace from the value found in the attribute Inherits.

The result should look like this:

<%@ Page language="c#" AutoEventWireup="false"
                       Codefile="myWebPage.aspx.cs"
                       Inherits="myWebPage" %>
Share

C# 101: Extension Method Creation For Variables and Enums

Class101 With the advent of C# 3.0 in .Net 3.5 one can create extension methods for common tasks for any existing types and enums which one finds in their code. This is a quick how-to article which provides those two examples using an integer and a user defined enum.

Basic Extension Example

Sometimes one needs to know when an integer value is negative. Here is an extension method to do that and its usage example.

public static class MyExtensions
{
    public static bool IsNegative( this int value )
    {
        return (value < 0) ? true : false;
    }
}
  1. Step one create a static class.
  2. Create a static method return type can vary to suit the target operations needs.
  3. Use the this keyword in the input parameters of the type which the extension will be used by.

In the above case we want integers to report if they are negative or not. Here is the usage:

int value = 1;

Console.WriteLine( value + " is " + value.IsNegative() );
value = --value;

Console.WriteLine( value + " is " + value.IsNegative() );

value = --value;
Console.WriteLine( value + " is " + value.IsNegative() );

/* Output
1 is False
0 is False
-1 is True
*/

Enum Example

Enums can have extensions in C# as well and are very functional.

This example is similar to the previous but we will deal with software development states. The first two states are test related and we will create an extension to determine if the state is in test or not.

public enum States { Test, UserAcceptance, Development, Production, Maintainence };

public static class MyExtensions
{
    public static bool IsInTest( this States state )
    {
        return state < States.LastTestState;
    }

}

So every state before Development is considered a “Testing” state. Here is its usage:

States current = States.Test;
Console.WriteLine("State: " + current + " is " + current.IsInTest());

current = States.Development;
Console.WriteLine( "State: " + current + " is " + current.IsInTest() );

/* Output:
State: Test is True
State: Development is False
*/

HTH

HTH

Share

C#: IEnumerable, Extension Methods, Lambdas to combine a List of Integers into a String

(Updated 3/26/2011 works on .Net 3-4)

In C# 3.0 (.Net 3.5/4.0) one can use the extension methods which work on IEnumerables to help with processing or converting your generic lists. This quick article shows how one can quickly join a list of integers and print them out as one sentance of “1 2 3 4 5”. Obviously there are other ways of doing this, but this gives one an overview.

Select Extension to Project Our List To Strings

Since the generic List<> inherits from IEnumerable we can use its extension methodd to do our dirty work. Look at the code here:

List<int> items = new List<int>() { 1, 2, 3, 4, 5 };    

Console.WriteLine    
    (    
    string.Join    
        ( " ",    
         items.Select(    
         item => item.ToString()    
        ).ToArray()   
    )   
);
  • Line 01: Here is our list of integers which we will want to eventually convert to a string “1 2 3 4 5”.
  • Line 05: The old static string.Join will do our dirty work by joining each of the items with a space for better reading. We just have to get it an oldstyle string array to it though.
  • Line 07: The extension Select method, will project (enumerate) over each item within our integer array and we will specify a new projection of strings using a lambda.
  • Line 08: Here is the lamda function which basically tells the compiler that for each now named item in items; simply convert it to its string counterpart.
  • Line 09: *Sigh* as mentioned above, string.Join needs the old style array, do that conversion here with the help of antoher extension!

Without String.Join Using Another Extension Method Aggregate

To remove the need of string.Join we will use the extension method Aggregate. Aggregate allows us to accumulate or aggregate values. Let me explain in code to achieve the same results as above:

List<int> items = new List<int>() { 1, 2, 3, 4, 5 };    

Console.WriteLine    
(    
   items.Select( item => item.ToString() )    
        .Aggregate<string, string>    
           (    
             string.Empty,    
            ( string prev, string current )   
            => prev +   
                     (prev == String.Empty ? current : " " + current)   
           )   
);
  • Line 05: We again use the Select extension/projection to convert our integers into string numbers.
  • Line 06: The aggregate method applies/projects an accumulator Lambda functon of our specification over the list of strings. Think of the Aggregate method as one which is stateful, for we will receive the results of the previous operation and be able to join it to the current. Line 04 simply tells the compiler that are working with two strings on input and output. One string is the previous aggregation operation and the other is the current item in the list being enumerated over during its processing.
  • Line 08: Since our aggregate takes two strings, we need to seed the process. The first call will use this string.Empty which will act as the first previous value to be married to the first current item in the projection/enumeration.
  • Line 09: This begins our declaration of the lamda function to use, it expects two strings, a previous accumulated string value and the current string item in the projection.
  • Line 10: What ever came before, we are going to marry it to the current. Here is why we need to seed string.Empty into the very first call.
  • Line 11: The previous will be married to the current, but we need to anticipate the very first time it is run where the string will be empty. For that situation, just return the current value. Otherwise return the current value with a space such as ” 2″. That will be then be concatenated (+) to prev in line 8. This is where we simulate the string.Join.

There you go a few ways of using the extension methods of Select and Aggregate and toArray with their specific individual lamda functions in C#.

Share