Wednesday, May 11, 2011

Property Grid

So this is probably not something you would use everyday but a cool feature in .NET is the Property Grid control.  This control accepts an object and displays the public properties of that object int he same fashion as the property window inside of .NET.  It also allows editing of those properties that have a setter available.

I'm using this for a "What If" calculator that is geared towards developer testing of our loan decisioning code.  We are also hoping to expand this to be used by our customer's auditor(s).

Usage

Drop the control on your form and then simply set the "SelectedObject" property to the object you want to display.

Ex. 

object someObject = new object();
propertyGrid1.SelectedObject = someObject;

Advanced Steps

You'll notice that by default the object is a jumbled mess when it is displayed.  There is a very quick and easy way (no code required) to really clean this up.

First, go to your object and make sure you have the using statement for "System.ComponentModel".  This will enable you do add Attributes which the Property Grid will make use of at run-time.

Browsable:  This will tell the property grid not to display an object or property.  Above that property you simply put [Browsable(false)].

Category:  Like the IDE, this grid offers the options of sorting alphabetically or to group properties.  Useage is [Category("Name Here")] about the property that you want to group into  a given category.  Note: You can only assign one category per property.  I found that to be a bit of a bummer but you could always create another property that accesses the same variable and assign it to another category I suppose.

Those are just two of the attributes available.  Some other useful ones are for read-only, default value, and a user friendly description of the field.


Monday, April 11, 2011

ClickOnce Error in .NET After Password Change

I ran into this issue and found few sites actually document what to do.

If you change your password (or password changes on a a remote login) and you try to do a ClickOnce deployment you may get an error that it can't publish because it can't find the specified directory.

The solution is to map a drive to that remote location and check the "use different credentials" button.  Use the credentials for that mapped drive and once you've successfully connect then retry publishing.

Basically, the password gets cached and .NET tries using the cached settings instead of prompting for a new login/password.

Thursday, December 2, 2010

Object Comparison

Overview


So this is a really quick example of how you can compare two objects to see if they are the same or not using reflection.  This allows you to compare 2 objects (see limitations below) without having to modify them.

Basically what this example does it loop through the properties of two objects and return a boolean if they are the same or not.  If they're not the same, an output list shows what values differ.

Sample Code

The basic code to do the comparison is as follows:

public static bool IsSame(object a, object b, out string differences)
        {
            differences = string.Empty;
            bool isSame = true;

            if (a.GetType().Name != b.GetType().Name)
            {
                isSame = false;
                differences = "Type does not match!";
            }        

            PropertyInfo[] propertyInfos; //array to store object properties
          
            //query the object to get the list of properties contained in this object
            propertyInfos = a.GetType().GetProperties();
          
            // sort properties by name
            Array.Sort(propertyInfos,
                    delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
                    { return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });

            //loop through the properties to compare to object b.
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                string aValue, bValue;
                aValue = propertyInfo.GetValue(a, null).ToString();
                bValue = propertyInfo.GetValue(b, null).ToString();

                if (aValue == bValue)
                {

                }
                else
                {
                    isSame = false;
                    differences += string.Format("{0}: {1}, {2}" + Environment.NewLine, propertyInfo.Name, aValue, bValue);
                }
            }

            return isSame;
        }

Now, there is a problem with this code... a property is considered a public member that has a "GET".  So in the example below... I get a "true" that the objects are the same but in reality the public "BIO" isn't getting checked because its not a true "property" as it doesn't have a GET... its more of a variable.  I did this intentionally to show some considerations for using reflection to compare an object.

So here is my definition for my "Person" object in the example:


    public sealed class Person
    {
        private string m_FirstName;
        private string m_LastName;
        private int m_Age;

        public string FirstName { get { return m_FirstName; } set { m_FirstName = value; } }
        public string LastName { get { return m_FirstName; } set { m_LastName = value; } }
        public int Age { get { return m_Age; } set { m_Age = value; } }
        public string Bio;

        public Person()
        {

        }
    }

And this is the actual test method:


Person a = new Person();
            Person b = new Person();

            a.FirstName = "John";
            a.LastName = "Doe";
            a.Age = 55;
            a.Bio = "John likes tacos.";

            b.FirstName = "John";
            b.LastName = "Doe";
            b.Age = 55;
            b.Bio = "John likes chips.";

            /*a.FirstName = "John";
            a.LastName = "Doe";
            a.Age = 55;
            a.Bio = "John likes tacos.";

            b.FirstName = "Jane";
            b.LastName = "Doe";
            b.Age = 22;
            b.Bio  = "Jane likes apples.";*/

            bool result;
            string differences;

            result = Compare.IsSame(a, b, out differences);

            MessageBox.Show(differences, string.Format("Are these the same? {0}", result.ToString()));


Notice  I commented out a snippet that you can uncomment and run to show the differences between the objects.

Alternatives


The pro to this comparison is that I can determine what values were different.  The con (as I've shown) is that this needs more fleshing out because public members like "Bio" didn't get pulled in and checked... and it was different.  Also, if I had a property that returns an array... I'm not checking the array and the ToString() would likely return just the type of the array/collection and not compare the individual members.

Some alternatives I can think of off the top of my head... I could convert both objects to binary and if they were the same binary output... the binaries would be the same (or the XML).  But it wouldn't tell me what changed.

I could also write an override function or override the "ToString" to output all the values such that I could compare the ToString results of the two objects.  In that same vein I could implement IComparable to allow the CompareTo function in order to determine if my objects are the same or not.

I guess my point there is that this is one potential way of solving the problem of comparing objects but there are others as well.  Which you use depends on your needs.

Wednesday, November 24, 2010

Should I build a "Windows" or "Web" App?

Hundreds of blogs have been written about the topic but I thought it would be worth re-visiting again.

A lot has changed in the last few years in the web world and has given some parity to the Windows vs Web app debate.  I don't think there is a clear winner but probably scenarios where one might make sense over the other.

Deployment/Bug  Fix process is one area I really think requires some consideration when choosing Windows vs.Web.  If Debbie in Accounting has a problem with a screen that only she uses... in the Windows world I can give her a new executable (via Click Once or XCopy, etc) and she's good to go; nobody else impacted.

In the web world, a production fix could require all the users to get out of the system.  If you're running a state-aware site... dropping in a new DLL will cause the sessions to restart.  (Note this applies to changing the code behinds; you can change the ASPX pages.)  To prevent this, you need a web application that is stateless (or uses cookies or some other method of storing information) so updates will not hose up everyone else.

Also web development tends to take longer than windows development because of the additional requirements such as security and optimizing performance.

Aside from that area, to me anyhow, there is a lot of similarities between the platforms.

Wednesday, November 10, 2010

Object Serialization in .NET

Serialization and its counter-process (Deserialization) is a mechanism to "package" an object for transport to another application or process.

You might want to send a stream of data over a web service, store it in a database, or need some type of interop way to transport an object across system.

The two main methods of serialization in .NET is the Binary and XML.  In a binary serialization, the object is converted to (get this) a binary stream; which is the fastest method of serialization.  Alternately with the XML serialization the stream is plain text which is better for interop.  One key note is that XML doesn't preserve the data type as well as binary but binary is really only useful for .NET to .NET type communication/transport.

Prerequisites to serialization... Serialization is not "free" in the sense that you have to do some work to make your classes/objects serializable.  The easiest way to do this is to mark your class with the attribute as shown here:

    [Serializable]
    public sealed class SomeObject
    {
        public int n1 = 0;
    }

This works because basic data types like int, string, etc .NET already knows how to serialize. However, if I had another custom class it would need to be marked as Seralizable as well.  This can has a cascading effect (all objects in the tree must be serializable [or marked as NonSerialized]) so keep that in mind when looking into this solution.

As I just alluded to if you want something to skip the serialization step then it needs to be marked as [NonSerialized] but keep in mind that object will be null when you Deserialize your object.

A simple example of how to serialize an object:

//Required namespaces
using System.IO; //required for stream
using System.Runtime.Serialization.Formatters.Binary; //required for binary formatter
using System.Runtime.Serialization; //required for Formatter Interface

SomeObject obj = new SomeObject();

IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream("MyFile.bin",
                                     FileMode.Create,
                                     FileAccess.Write, FileShare.None);

formatter.Serialize(stream, obj);
stream.Close();

As you see above we use a formatter. In this case we used the Binary Formatter but could have used the XML Formatter as well.  The formatter as the name suggests converts the object into the specified serial format and puts it into a stream.

In this case I put the object into a file but I could modify the code and store it in a string or some other container.

As I mentioned earlier now with this object stored in a stream/file/whatever we can now do with it what we please.  For our example, we'll say that this binary goes into a folder for processing by a Windows Service.  In the service it is very simple to pull the object back into memory and start working with it...

FileStream fs = new FileStream("MyFile.bin", FileMode.Open);
BinaryFormatter readFormatter = new BinaryFormatter();
SomeObject serialObj = (SomeObject)formatter.Deserialize(fs);

Just like that we now have our object back and can start working with it.

Limitations...  Some things to keep in mind when doing serialization ... I already mentioned that data that is marked as NonSerialized will be blank/null in the object.  But also keep in mind deserializing an object is not the same as creating a new object.  Therefore, the constructor don't be called.

Also, only public information is serialized.

Custom Serialization... I didn't touch on it but you can inherit the ISerializable interface and invoke your own GetObjectData method to write your own custom serialization for an object.  By default, you don't need to do this unless you have special requirements for the output of the serialization (say your formatting your XML to a schema that another system will consume, etc).

Thursday, November 4, 2010

Alternatives to Try Catch type casting

Back in the early stages of .NET in C# there were limited tools to determine if a cast would work or not.

So typically you'd see something like

int myInt = 0;

try
{
   myInt = (int)TextBox1.Text //some input
}
catch
{
   MessageBox.Show("This is not a valid integer.");
  return;
}

In 2.0 the TryParse came along.  TryParse will return a bool (if the cast worked or not) and put the value of the successful cast into a value.

Example:

int myInt = 0;

if !(int.TryParse(TextBox1.Text, out myInt))
{
  MessageBox.Show("This is not a valid integer.");
}

Visually, this is a little less code but is also a more legitimate way of testing your casting.  Really, you could do a lot more checks using Regular Expressions, etc but something like this is a simple way to do validation in simple scenarios... IE... you just need there to be a number in there not a number with a decimal and x number of digits before and after, etc.

That example was for simple data types... but we can use IS for more complex data types like objects.

The IS keyword basically evaluates if the object to the left of the IS inherits (or is actually) of the same type.  This is useful in places where you want to pass an object as something simpler than it really is to made your function more versatile.

Using the Try Catch paradigm we could do something like this...

public static boolean SaveData(object myObj)
{
     SomeBaseClass b = null;

      try
     {
          b = (SomeBaseClass)myObj;
          return b.SaveData(); //assumes that method returns bool
      }
     catch
     {
         return false;
      }
}

A simpler way is to use the IS keyword...


public static boolean SaveData(object myObj)
{
    SomeBaseClass b;

    if (myObj is SomeBaseClass)
  {
          b = (SomeBaseClasse)myObj;
         return b.SaveData();
   }
  else
  {
   return false;
  }
}

Now in a case like this I'd probably make my SaveData function accept a SomeBaseClass object instead of a regular object and call the save... or make the object implement some type of interface that any object wanting to use this method could call.

However, this is just to give an example of how you can evaluate objects.  Maybe you support some types of objects (or handle them slightly differently) and want to run them all through the same method and this way you can easily do that.

Wednesday, October 27, 2010

Tech Tidbits

Nothing really new to discuss in the world of .NET right now (but I've got some stuff in the works to show).

A new things from around the tech world.

1. iPhone for Verizon.  It looks like it will be happening soon.  AT&T has increased its termination fees and Verizon is going to offer iPads with unlimited data plans as two signs.

2. iPad competition.  HP and Asus among are offering table PCs comparable in features, size, and price of the iPad.  Expect more to come out in the near future.  Interestingly, many of these new tablets are running Windows 7.

3. Windows 8.  It is being reported that Windows 8 is about 2 years aways (give or take).  Windows 7 was just released a year ago.