A little story about .GetType()

21. May 2010

Last week I was writing some code with a co-worker and a line of code similar to the following came up:

if (object.GetType() == typeof(T))
{
	// ... more code here.
}


The question came up, “doesn’t this use Reflection”?  My response was that the .GetType() method itself doesn’t use reflection, but instead evaluates the object’s metadata from the CLR at runtime and produces the relevant type information.

Then, I ran across this from TweetDeck today:

To the guy ("who is always right") that said GetType() doesn't use reflection: http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx

Now, let’s not kid ourselves here, I’m certainly not the guy who is always right.  So, ready and willing to be wrong I started reading the rather innocuous post from MSDN on the subject:

Here's a simple example of reflection using the static method GetType - inherited by all types from the Object base class - to obtain the type of a variable:

C#

// Using GetType to obtain type information:
int i = 42;
System.Type type = i.GetType();
System.Console.WriteLine(type);
 

Indeed, MSDN does say that invoking .GetType() is an example of using Reflection.  My original comment that .GetType() didn’t use Reflection was based on my (inaccurate) definition of reflection – that an object is reflected upon when it becomes loaded into memory for the sole purpose of achieving this reflection.  I suppose the difference is one of perception, really, but here it’s clearly caused confusion.

Then I ran across this post supporting my assertion, that calling .GetType() in fact constructed the type information at runtime directly using a hook into the CLR.  Is this the same as reflection?  My original point that this wasn’t reflection was really one more of performance than the syntax.  I wonder what Ritchie Swann would say now regarding his original comments on the matter:

As for how it works - the GetType() function is marked with the special attribute [MethodImpl(MethodImplOptions.InternalCall)]. This means its method body doesn't contain IL but instead is a hook into the internals of the .NET CLR. In this case, it looks at the binary structure of the object's metadata and constructs a System.Type object around it.

The question of performance, in my mind, can really only be answered by doing a comparative analysis.  How much work does .GetType() do anyway, and is it the same as other methods of Type checking?  I decided to check it out.  Consider the following rather simple class:

namespace TypeReferenceChecking
{
    class Program
    {
        static void Main(string[] args)
        {
            TestIs();
            TestGetTypeIs();
            TestGetTypeEquals();
        }

        static bool TestIs()
        {
            var newObject = new SampleType();

            return newObject is SampleType;
        }

        static bool TestGetTypeIs()
        {
            var newObject = new SampleType();

            return newObject.GetType() is SampleType;
        }

        static bool TestGetTypeEquals()
        {
            var newObject = new SampleType();

            return newObject.GetType() == typeof(SampleType);
        }
    }

    class SampleType
    {
    }
}

Looking at the disassembled C# source for this assembly with Reflector, you’ll see the following:

internal class Program
{
    // Methods
    private static void Main(string[] args)
    {
        TestIs();
        TestGetTypeIs();
        TestGetTypeEquals();
    }

    private static bool TestGetTypeEquals()
    {
        SampleType newObject = new SampleType();
        return (newObject.GetType() == typeof(SampleType));
    }

    private static bool TestGetTypeIs()
    {
        new SampleType().GetType();
        return false;
    }

    private static bool TestIs()
    {
        SampleType newObject = new SampleType();
        return (newObject != null);
    }
}

At first glance, it appears that calling .GetType() in your code, in fact, calls the runtime method .GetType(), which MSDN says is reflection.  But what about the argument that .GetType() retrieves information from the CLR hooks itself, not from an image of the assembly containing the type.  I was dying to find out, so I used Reflector on the .GetType() method itself:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public extern Type GetType();

Sure enough, it’s exactly what Ritchie Swann eluded to.  Then I started thinking about the real question.  If .GetType() gets type information from the CLR and constructs a new instance of System.Type, how expensive is that construction? 

[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
protected Type()
{
}

It would be lovely to say that we get more answers here, but we don’t.  There is a static constructor on Type that initializes empty types, filters, etc. but no instance constructor.

So, the million dollar question, that really only Microsoft can say is:

For purposes of evaluating type comparison, is using .GetType() for an object that’s already in memory at runtime the same as evaluating type information from a type that’s not already loaded in memory?  If not, do you call both reflection?  This was the distinction that I really wanted to make the other day in my conversation with my coworker, that doing this runtime check is harmless and doesn’t cause excess work for the CLR (despite what it may be called).

I look forward to some great chats at TechEd with folks who will likely gladly weigh in.  Got your own opinion?  Comment below.

Development

Using SharePoint 2010 Beta 1 REST services on Windows 7 or Windows Server 2008 R2

27. February 2010

Today, I’m presenting this session from PDC at a local code camp.  In setting up my demo, I’ve been trying to get the SharePoint 2010 beta 1 server setup so that it can be queried using WCF Data Services (formerly ADO.Net Data services).  Whatever I try, I continue getting the following error:

WebHost failed to process a request.

Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/40906347
Exception: System.ServiceModel.ServiceActivationException: The service '/_vti_bin/listdata.svc' cannot be activated due to an exception during compilation.  The exception message is: Could not load file or assembly 'Microsoft.Data.Services, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified..

The good news is that there is a solution for this problem.  The ADO.Net Data Services 1.5 CTP 2 runtime needs to be installed as well as a patch.

The runtime can be found at: http://www.microsoft.com/downloads/details.aspx?FamilyID=a71060eb-454e-4475-81a6-e9552b1034fc&displaylang=en#filelist

The patch is available at:
http://www.microsoft.com/downloads/details.aspx?familyid=79d7f6f8-d6e9-4b8c-8640-17f89452148e&displaylang=en#filelist

Development ,

Presenting today: Behind the Scenes of SalesForce.com and Microsoft Dynamics CRM 4.0: The Developer’s Story

12. November 2009

I’m doing a webinar today for my company, Tribridge, entitled “Behind the Scenes of SalesForce.com and Microsoft Dynamics CRM 4.0: The Developer’s Story”.  Long titles aside, I’m super excited about delivering this content to a technical audience. 

This is actually a follow-up presentation from a webinar that my colleague Seth Kircher did a few months back.  If you didn’t see the first part, you may want to watch it before attending today’s webinar.

Register for today’s webinar.

Community Events, Development

Silverlight 3 Linkapalooza

23. September 2009

So I’ve been a very, very busy bee with a bunch of projects, and there’s been no lack of well-deserved teasing for not posting to this blog in 8 months.  I guess the best way to silence the critics would be a good-old-fashioned link-off.  Here’s my list of high quality Silverlight 3 content that you’ve got to check out.

Showcase Sites & Samples

Expression Blend & SketchFlow

Interactivity & Behaviors

Application Lifecycle & Composition

Navigation

DataForm

Data Binding / Data Services (not RIA Services)

RIA Services

WPF / XAML cross-breeds

Connecting with the Silverlight Team

Development , ,

Where in the world is Brandon Kelly?

27. January 2009

I can’t believe February 2009 is already here.  Seems like only yesterday I was intently waiting on my flying car like the rest of us, and now I’m living in the future!  In case you’re not up to speed, there’s several great community events coming up – and I’ll be doing my usual code singing, beer slinging routine.

February 7 – South Florida Code Camp
I’ll be presenting on writing Line of Business applications with Visual Studio 2008 and Silverlight 2.  This presentation will be an end-to-end demo of data design/maintenance using VSTS Database Edition, modeling with ADO.NET Entity Framework, building a business layer and then UI with Silverlight 2.  If you didn’t make Tampa Code Camp in December this is the show to see.

February 17 – Sarasota DEV User’s Group
I’ll be in Sarasota the night of the 17th presenting on Visual Studio Team System 2010.  This will be the demo that I did at MDC (MSDN Developer Conference) in December, so if you missed the conference, PDC and still want to see some hands on VSTS 2010, I’ll see you in Sarasota!

Looking forward to a great month, quarter and then year with the local developer communities.

Community Events

My “Chalkboard” Visual Studio 2008 Theme

27. January 2009

Many people around the office have taken notice of my Visual Studio 2008 theme, which I’ve affectionately called “Chalkboard”.  I put together this theme and then tweaked it over the past few months to make hours in front of Visual Studio 2008 easier on my eyes.  Here’s a screen grab.

The high-contrast colors (dark background, light foreground) take some getting used to, but they’re much easier on the eyes after you do.  For those who are interested, I’ve exported my Font and Color settings as a Visual Studio 2008 theme.

Download my Visual Studio 2008 “Chaklboard” theme.

Technorati Tags: ,

Development

Using Help Filters in Visual Studio

21. January 2009

Last night I was at the Tampa SQL Server User’s Group attending a good intro on VSTS Database Edition GDR presented by Catapult Systems.  After the session, one of the attendees asked me if there was any way to get rid of the SQL Server Compact Edition help from his Visual Studio help collection.  One way to do this is to use the provided help filters, which allow users to set preferences on what content they would like to see in help.  Here’s the link to MSDN that explains the filters:

Using Help Filters in Visual Studio (MSDN)

Another way to do this is to uninstall the specific content that you want removed from the collection.  Simply run the MSDN uninstaller from the Control Panel and modify your installation.

Development

Timeout and Workflow issues when using the Deployment Manager in Dynamics CRM 4.0

12. January 2009

I've been trying to re-deploy a CRM 4.0 installation from a client's site into our development domain so that I can work with some of the data in the system.  Using the provided CRM 4.0 Deployment Manager is pretty easy (instructions found here), but wasn't working. 

The deployment manager would run for a good 30+ minutes and eventually come back to me with a SQL Server Timeout error.  The details of this error follow:

Import Organization (Name={Name}, Id={ID} failed.

The changes made during Import Organization could not be rolled back. Please manually delete the Organization database from the 'SBCRM01' SQL Server if it was not successfully deleted.

System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
… 
   at Microsoft.Crm.Tools.Admin.ImportOrganizationInstaller.Import(Guid organizationId, String organizationUniqueName, String organizationFriendlyName, String sqlServerName, String databaseName, Uri reportServerUrl, String privilegedUserGroupName, String sqlAccessGroupName, String userGroupName, String reportingGroupName, String privilegedReportingGroupName, ICollection`1 users, MultipleTenancy multipleTenancy)

I Googled, hooked up SQL Server Profiler and searched Microsoft’s knowledge base – desperate for some sort of answer to this problem.  I finally found a forum post online that described a similar scenario being resolved by installing Microsoft Dynamics CRM 4.0 Update Rollup 1

It wasn’t until I looked at the deployment log file that I realized that the timeout expired error was really just a symptom of another problem.  Turns out that below the Timeout exception I found another exception message that describes what’s really going on.

Import Organization (Name={Name}, Id={ID}) failed with Exception:

Microsoft.Crm.CrmException: Unable to find metadata information for attribute {attribute_name}
   at Microsoft.Crm.Workflow.ObjectModel.MetadataProvider.GetAttributeMetadata(EntityMetadata entityMetadata, String attributeName)

   at Microsoft.Crm.Tools.Admin.ImportOrganizationInstaller.Import(Guid organizationId, String organizationUniqueName, String organizationFriendlyName, String sqlServerName, String databaseName, Uri reportServerUrl, String privilegedUserGroupName, String sqlAccessGroupName, String userGroupName, String reportingGroupName, String privilegedReportingGroupName, ICollection`1 users, MultipleTenancy multipleTenancy)

What the heck is this?  Turns out, the issue is caused by having workflow in CRM that references an attribute that is subsequently deleted.  Per Joel CustomerEffective (forum post), here’s some things you can do to resolve the issue:

1. Recreate the missing attribute (you can delete after import).
2. Delete any rows that reference that attribute from the workflowdependencybase table
3. Import the organization into an environment that is pre-rollup 1
4. Wait for KB958571 to be released--they are testing it now.  If you search for it, you will find the KB article for it, but the hotfix has been redacted pending further testing.

Of course, KB958571 talks about a hotfix that isn’t publically available.  Sad – really sad, but have no fear!  After wasting 6 hours today working on this problem, I’m still waiting on getting an answer from Microsoft about the availability of the patch.  I’ve attempted solution #2 (removing the dependencies from the source database before performing the import) without success.  Options #1 and #3 aren’t available to me at the moment.  If you know of a better solution, please post a comment to this blog!

Development ,

Windows 7 on my Dell Inspiron 6400

10. January 2009
Image representing Windows as depicted in Crun...

I first received Windows 7 at Microsoft PDC this year, but I waited until a little further down the release path (beta 1) to do my first install.  After reading several reviews (all mostly positive) online that don't hesitate mentioning Windows 7's superior performance over both VIsta and XP, I decided to take the plunge and install the new O/S on my home laptop.

On the whole, I've really liked using Windows 7, despite several glitches getting things running on my Dell Inspiron 6400.  On the up side, there's an marked improvement in performance, boot times, memory footprint and overall responsiveness from Windows -- not to mention a host of new helpful features.  As you might expect with any beta product, there were some glitches along the way.  Here's a re-cap of some things to watch for if you're installing Windows 7 on the wildly popular Dell Inspiron 6400/E1505 series laptop.

No 64-bit drivers exist for ATI Mobility Radeon X1400
It won't take you long after installing the 64-bit edition of Windows 7 to realize that you can't change your video resolution to the factory recommended 1680x1050.  You'll also be relegated to a Windows Vista Basic type experience, with no Aero support.  There's no 64-bit drivers available for the ATI Mobility Radeon X1400 that's inside the Dell Inspiron 6400/E1505 series laptop.  Unsupported, unsigned drivers won't work.  AMD's web site asks that you contact Dell for drivers (won't be buying another ATI video card again as the support is non-existent).  In addition, Dell has nothing to say about 64-bit support for the ATI Mobility Radeon series.  The only way to resolve this issue is to install the 32-bit version of Windows 7, where the 32-bit Vista drivers are supported.

About that Microsoft Bluetooth Mouse...
If you're anything like me, you don't use the included Trackpad on your laptop (and have probably disabled it).  The Windows 7 installer automatically paired with my Bluetooth mouse (nice) during installation, but then after installation was complete Windows lost all knowledge of my mouse on first boot.  I went to the new Device Center and added a new device (which it detected fine).  Unfortunately, it didn't pair, citing some unspecified error and prompting me to troubleshoot.  The troubleshooting did nothing.  Since I'm persistent, I tried it again, and again, and again, and the 4th time it worked.  Not quite sure what's happened here but I haven't had any trouble with the mouse since.

No matter what Windows 7 tells you, don't install AVG Anti Virus
One of the first things that Windows will bring to your attention (through the new Action Center) is the need to install some anti-virus software.  Since Windows Live OneCare isn't supported, Windows provides 3 recommendations for compatible software.  I chose AVG Anti-Virus, and soon after installation started experiencing random BSOD crashes.  The crash talks about tdx.sys being the unfortunate victim of a stop error.  After some research, I was able to ascertain that this crash is due to some legacy network drivers not playing well with Vista (and assumedly Windows 7).  I wasn't sure what this had to do with security software until I remembered all the fancy stuff AVG was going to install on my system to prevent the mitigation of spyware.  Sure enough, uninstalling AVG stopped the BSDO crashes.

There's 100s of great new features in Windows 7, but the bottom line is that this is the release that Vista probably should have been.  The base O/S without extra software installed on my Dell Inspiron runs at about 450mb RAM utilization and 2% CPU usage.  In contrast, Vista on the same box ran at about 1100 Mb RAM utilization and 5% CPU usage when idle.  This improvement is badly needed and by itself seems to be enough to get 2.5 million beta testers to rush for an upgrade.

Technorati Tags:

Consumer Electronics

Troubleshooting guide for TFS installation

7. January 2009

Looks like the good folks in Redmond got some time to write up a much-needed troubleshooting guide for TFS server installations.  You can find the guide on MSDN using the following link:

Troubleshooting installation of Team Foundation

The guide goes over how to interpret the installer log files, as well as diagnosis for many common TFS errors.  Here's a list:

  1. Error 32000. The Commandline ‘[1]’ returned non-zero value: [2]
  2. Error 29112. Team Foundation Report Server Configuration: Either SQL Reporting Services is not properly configured, or the Reporting Services Web site could not be reached. Use the Reporting Services Configuration tool to confirm that SQL Reporting Services is configured properly and that the Reporting Service Web site can be reached, and then run the installation again. For more information, see the Team Foundation Installation Guide.
  3. Error 29109. Team Foundation Report Server Configuration: SQL Reporting Services configuration encountered an unknown error. Verify that you have sufficient permissions to configure SQL Reporting Services, and try again.
  4. Error 28806. An unexpected error occurred. Verify that SQL Server Reporting Services is installed and running on the Team Foundation app tier and that you have sufficient privileges to access it. For more information, see the setup log.
  5. Error 29000. An unexpected error occurred. Verify that SQL Server Reporting Services is installed and running on the Team Foundation app tier and that you have sufficient privileges to access it. For more information, see the setup log.
  6. Error 28805. The setup program cannot complete the request to the server that is running SQL Server Reporting Services. Verify that SQL Server Reporting Services is installed and running on the Team Foundation app tier and that you have sufficient permissions to access it. For more information, see the setup log.
  7. There is an error with the collation settings for SQL Server. The collation settings are not compatible with Team Foundation Server.


There are also sections for troubleshooting the installation of Team Build or Team Explorer in Visual Studio, as well as some helpful hints for post-installation pains.  This article has now taken the place of a dozen of my favorites -- thanks Microsoft!

Technorati Tags: ,,

Development , ,