Welcome to MSDN Blogs Sign in | Join | Help

Visual Debugger for MSBuild Projects

Folks, Hi!

A recent feature poll on the MSBuild blog seems to indicate that a debugger for MSBuild projects is the #1 vNext request from you. Lot of other folks (such as here and here) have explicitly blogged about this requirement.

Over the last week I put together a Visual Debugger for MSBuild Projects. The v1 alpha feature list looks like:

v1 Feature Set:

  • Load project and arbitrary target files
  • Set/View build environment
  • Step-Into tasks and targets (F11), Run (F5), Break execution, Step into imported projects, step into CallTarget & MSBuild tasks, task & target batching
  • Set breakpoints on tasks and targets, delete/view breakpoints, locate breakpoints in code
  • View call stacks (esp. useful for stepping into CallTargets & MSBuild tasks), locate stack frame in code
  • View debugger messages, MSBuild traces in Output window
  • RO View of evaluated Items and Properties in break mode
  • Handles out-of-box VS2008 projects and complex Microsoft's Developer Divisions's MSBuild based builds
  • Requires only .NET Framework 3.5 RTM (no VS2008 required)

I have also uploaded the binaries and how-to-get-started instructions on http://www.codeplex.com/msbdbg.

Please head over there to give this a spin. I have also listed there the known issues, the v2 plans, and other details there.

I am looking forward to listening to you on the right, wrong, the good, bad, the ugly and anything else that you will care to tell me about.

I am hoping this will go some distance it helping everyone get away from printf debugging and get into full fledged debugging for MSBuild projects. Esp. considering MSBuild projects files are no longer used only for builds. (Why, my wife has even filed a patent for using MSBuild as a test harness)

Here are a few screen shots:

MSBuild Debugger Saying 'hello'...

opendbg  

Set Breakpoint and Select Target to Debug...
setbpandselecttargettodebug
Breakpoint Hit and Output Window...
bphitandoutputwindow
Break at Arbitrary Location, See Call Stack and Properties...
breakNcallstackNproperties
Step-In, See Items and Active Breakpoints...

stepinNitemsNbreakpoints

Posted by parthopdas | 10 Comments

Model-View-Controller Design Pattern...

This post is really to update my blog so that is doesn't get deleted due to massive levels of inactivity.

I am also experimenting with Windows Live Writer - it totally kicks ass!

Windows Liver Writer

Anyways getting back to the point...

This particular diagram conveys pretty much everything about M-V-C:

Model-View-Controller

 

Some additional links on M-V-C (Yes, yes... Google can give this information - but I am trying to save my blog really)

See you later...

Posted by parthopdas | 1 Comments

MEDC India 2006, Bangalore

Hi Folks...

The 1st ever Microsoft Mobile & Embedded Developer Conference in India – MEDC-India 2006 – was held at Bangalore’s Grand Ashok Hotel during the 4th-6th April 2006.

Aarthi and I delivered a session on Creating Custom Controls For Managed Code With Designtime Support In Visual Studio 2005, targeted at folks indulging in custom control development on .NET CF.

We enjoyed delivering the session and the response from you guys was awesome. It was really nice talking to you guys. Thank you for all the feedback. We are looking forward to meeting you again and please keep the feedback coming in. Please also feel free to contact me at parthad at microsoft dot com if you need any help from us.

In case you want the session material, it is attached (MOB301 - MEDC2006.zip). It contains the slides as well as the demos and walkthroughs.

On a lighter note, we did take a couple of photos. Here is one of them:

Guys from VSD team @ MEDC-India 2006 

The guy closest to the camera is Anand. The 13 year old kid is Aarthi. Partho is on her left. Sriram on her right. Varada on Sriram's right. On Partho's left is Amit and on his right is Gopinath.

Oh another thing... We met the great Doug Boling. The guys is simply awesome - delivering 5 back-2-back sessions in a single day - all hardcode WinCE kernel related! Manav and I had beer with him and talked about everything from why Hillary Clinton would/wouldn't become the President to what sux in Visual Studio 2005!

Thats all for now... See you in a while!


Posted by parthopdas | 9 Comments
Attachment(s): MOB301 - MEDC2006.zip

Destination SQL Server 2005 (Mobile Edition)

Hi Folks...

The title of this post may make it sound like a movie. But it ain't. This is a contemporary post noir set on the devices of a gritty, yet colorful SQL Server neighborhood... :D (That was gross, I concur! Hopefully the meat of the post will have some substance and better humor than its opening line)

The reason for this post was is the following question posted on one of our internal Data on Devices related aliases.

We wish to push SQL Server Mobile database file from a desktop application developed in VS2005 to the mobile device Here it is in a nutshell:

1) POPULATE the mobile database with data on the desktop
2) PUSH the mobile database to the mobile device

We have following Questions

1) Figuring out how to populate a SQL Server Mobile database file from a desktop application developed in VS2005 (and to do so directly, without RDA, Replication or XML).
2) Identify the best way to PUSH the above SQL Server Mobile file to the mobile device (i.e., do we still use RAPI's DesktopToDevice?)
3) Determining which .DLL's our application will need to install on the end-users Desktop PC to enable both the POPULATE and PUSH functionality as developed
4) Making sure we have Microsoft's permission to redistribute said .DLL's.

As you have noticed, we have a rich data-on-devices story with Visual Studio 2005. A lot of work went into this area since Visual Studio 2003 and data-on-devices story is now on par with the desktop data scenarios. Which means that the answer to the above question needs to be broadcasted to a much bigger audience...

Here it is, from Laxmi Narsimha Rao, my colleague from SQL Server 2005 Mobile Edition team:

I wanted to let you know the following things before jumping into answering your questions:

1) SQL Mobile is unrestricted only for devices and tablet-pc
2) SQL Mobile is unrestricted for desktops that have either VS 2005 or SQL 2005 installed

Given that information, coming to your operations:

1) POPULATE – This is done on the desktop. It means that you should either have VS 2005 or SQL 2005 in order for SQL Mobile to work. 
    a. Say the desktop has VS 2005, you can populate the database using our System.Data.SqlServerCe namespace 
        i. SqlCeEngine – Create Database 
        ii. SqlCeConnection and SqlCeCommand – Populate the database 
        (Please note that SQL Mobile supports parameterized queries. Let the customer know about this to get best out of SQL Mobile.)
2) PUSH – This is nothing but copying the database file created in the above step to the device. There are lot of ways you can do this: 
    a. VS 2005 Auto Deployment – Add SQL Mobile .SDF file to the device project and when you hit F5, it automatically deploys the .SDF file too 
    b. Use Active Sync File Explorer and copy manually 
    c. Use RAPI

And the answers for your questions:

1) RDA, Merge Replication – None of these is needed to populate the database when you have the data at your hand. But any of these is needed when you have the data in SQL Server.
2) As explained above
3) This depends on what your device app is going to do with database on device. If your app is using the DB just as a local store, then you just need first two cabs. If your device app is going to do some sync with SQL Server, then you need the third cab.  
4) Covered by earlier answers and information 

Let me know if you need some more info and/or other clarifications on the above topic. In fact any topic on Data-on-Devices.

As a side note, I own the Visual Studio for Devices, Data components and I do have plans for a few posts on Data-on-Device. But if there is something specific that you want me to make a post on, I'd be glad. Just let me know...

See you then, in my next post...

Understanding the TypeDescriptor: A Metadata Engine for Designtime Code

Hi folks - long time no see... E.L.D.S.? Yeah, sure! Never mind that, here is a dump of my understanding of the TypeDescriptor. Hope you find it useful!

What is Metadata in the context of CLR? Read all about it here. And what makes this concept really powerful is that any code can access the CLR metadata engine (using managed and unmanaged API) to inspect any given managed code down to each IL instruction. The CLR metadata engine also has API to let other code emit managed code. But once emitted and baked, the CLR metadata engine will only let you inspect the managed code – you will not be able to extend or modify any of it.

Now we all know that the all-powerful and mighty .NET Framework Designtime infrastructure lets every component have 2 views of itself – a designtime view and a runtime view. You might have also observed that the designtime view is not quiet the same as the runtime view. If you haven’t, consider the following:

  1. Every Form on the design surface of a Visual Studio 2005 DeviceApplication project has a property called FormFactor. Can you locate it in System.Windows.Forms.dll using Reflector or ILDAsm or the Reflection API?
  2. If the ErrorProvider component is present on the design surface, all other controls on the design surface have new property called Error on errorProvider1. Can you locate this property in System.Windows.Forms.dll?

This means that the designtime infrastructure is displaying a metadata different from what is returned by reflection API. Clearly someone is modifying the metadata before the designtime infrastructure displays it. Now who would that be?

The System.ComponentModel.TypeDescriptor of course!

TypeDescriptor is a metadata engine provided by the .NET FCL. The MSDN documentation says the following:

... In contrast, TypeDescriptor is an extensible inspection mechanism for components: those classes that implement the IComponent interface...

That is not quiet correct. TypeDescriptor is an extensible inspection mechanism not just for components but for all Types and for individual instances of any given Type. Although if the target is a component, it may have a Site and the Site may proffer services, e.g. the ITypeDescriptorFilterService (discussed below) or the IExtenderProvider, which can further enhance the extensibility of the TypeDescriptor.

To restate: Unlike the native CLR metadata engine, TypeDescriptor lets you inspect as well as modify the metadata (add, change and delete) of the target in any conceivable manner. The term target, for the rest of this text will refer to an element of the set of all .NET Framework Types (including Types imported from COM) and all instances of every .NET Framework Type.

Note that an update to a Type’s metadata is visible for the Type and all its instances. But when the metadata of an instance of any Type is updated, the update is seen only for that instance. Metadata of the Type and its other instances are unaffected.

Also note that TypeDescriptor and Reflection API do not interoperate. While TypeDescriptor gets the initial metadata information using Reflection (explained below), further changes to metadata using TypeDescriptor is not visible using Reflection. Only the TypeDescriptor API will let you inspect the new metadata and update it further.

Here is an example of metadata inspection using TypeDescriptor:

using System;
using System.ComponentModel;

namespace InspectWithTD
{
   
class Program
    {
       
static void Main(string[] args)
        {
           
Console.WriteLine("Attributes on System.Object are:");
           
AttributeCollection attributes = TypeDescriptor.GetAttributes(typeof(object));
           
foreach (Attribute attribute in attributes) Console.WriteLine("- " + attribute.GetType().Name);

           
Console.WriteLine("\nProperties of a string object are:");
           
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties("A String");
           
foreach (PropertyDescriptor property in properties) Console.WriteLine("- " + property.Name);

           
Console.WriteLine("\nEvents on the AppDomain we are running in are:");
           
EventDescriptorCollection events = TypeDescriptor.GetEvents(AppDomain.CurrentDomain);
           
foreach (EventDescriptor @event in events) Console.WriteLine("- " + @event.Name);
        }
    }
}

In the following sections we will take a brief look at the architecture of the TypeDescriptor. Then we see what its capabilities are. And finally close the topic with an example. But before we get started, I suggest you open System.dll in Reflector, navigate to TypeDescriptor and disassemble the method implementations to get a deeper understanding.

Brief Architecture of TypeDescriptor

Internally, the TypeDescriptor creates (on demand) and maintains a stack of TypeDescriptionProvider (provider hereafter) for each target. Providers can be considered as plugins for the TypeDescriptor and they are the entities responsible for supplying the target’s metadata and for most other TypeDescriptor magic.

For Type targets, the TypeDescriptor can initialize the provider stack with a read-only provider that is built on Reflection API. Or with a delegating provider that is hooked up to delegate the calls each time to the latest provider for the Type’s base Type. This way the calls are handled by the latest provider for the Type’s base Type, if the Type doesn’t have provider stack by itself.

For instance targets, the provider stack can be the same as the provider stack of the instance’s Type. Or it can be initialized with a delegating provider that is hooked up to delegate the calls each time to the latest provider for the instance’s Type. This way the calls are handled by the latest provider for the instance’s Type, if the instance doesn’t have provider stack by itself.

Once the provider stack is initialized, the TypeDescriptor lets you add/remove custom providers to/from the stack. Custom providers need to extend TypeDescriptionProvider and can have a parent provider. They can selectively change the TypeDescriptor behavior for a given target by selectively overriding the TypeDescriptionProvider methods. If a parent provider exists, the methods of TypeDescriptionProvider delegate the work to the parent provider. This is how we achieve TypeDescriptionProvider chaining. The provider one on the top of the target’s provider stack (latest provider hereafter) is returned by TypeDescriptor.GetProvider and is the one doing most of the TypeDescriptor’s work as we are going to see below.

To proceed further we must understand the ICustomTypeDescriptor (custom type descriptor or CTD hereafter). Click on the link and see its API – isn’t there a striking similarity with its methods and metadata inspection methods of the TypeDescriptor? Indeed – the purpose of a CTD is to return the metadata for the given target. The default implementation of ICustomTypeDescriptor, the CustomTypeDescriptor, takes in a parent ICustomTypeDescriptor (to enable CustomTypeDescriptor chaining) in its constructor. If the parent exists, each method of the CustomTypeDescriptor simply delegates the call to the parent – else the methods return empty metadata.

TypeDescriptionProvider.GetTypeDescriptor returns the CTD supplied by a target’s provider. For instance targets another method, TypeDescriptionProvide.GetExtendedTypeDescriptor also returns a CTD. But this CTD implementation returns the metadata contributed to the instance by the Extender Providers. The default implementation of this returns empty metadata if the instance is not a component or it is not sited. Otherwise if the target is sited and the site proffers the IExtenderListService, which lists the extenders. If the site doesn’t proffer the service, the extenders in the target’s container are listed. From the list of extenders, the extended metadata is collected.

The TypeDescriptor methods that return the target’s metadata are in fact wrappers around the corresponding methods of the CTD obtained from the target’s latest provider. For Types, calling GetTypeDescriptor on the latest provider obtains the CTD. However obtaining the CTD for an instance is a little involved since the instance itself may implement ICustomTypeDescriptor. If it does, then the CTD returned is a merge of the ICustomTypeDescriptor implemented by the instance and the CTD supplied by the latest provider of the instance – but with a preference to the ICustomTypeDescriptor implemented by the instance. If the target doesn’t implement ICustomTypeDescriptor then the CTD obtained is the one supplied by the instance’s latest provider. This means any arbitrary object, by implementing ICustomTypeDescriptor, can dynamically modify the metadata obtained from it by the TypeDescriptor. Of course many of the TypeDescriptor method take in a boolean argument – which when true, simply tells the TypeDescriptor to ignore the instance’s implementation of ICustomTypeDescriptor.

A few of the above methods that return metadata of instances are a bit more sophisticated. For instance the TypeDescriptor.GetProperties that takes in an instance, determines the set of properties to return in as many as 4 successive stages. The output of each stage is fed to the next stage.

  1. First stage: The CTD is obtained (as above) from the latest provider and it returns the initial set of properties.
  2. Second stage: The input set is merged with the set of properties contributed by the Extender Providers. To obtain this set, GetExtendedTypeDescriptor is called on the latest provider for the instance.
  3. Third stage: If the component is sited and the site proffers the ITypeDescriptorFilterService, the input set is passed to the ITypeDescriptorFilterService to be filtered. This forms the basis of the IDesignerFilter that allows a ComponentDesigner to add/change/delete properties from the set of properties of the component it is designing.
  4. Fourth stage: The input set is filtered based on a set of attributes. The rules used for this filtering is explained well in the Remarks section here.

Whew! That is sophistication for you. The power you wield is just awesome! The above is for GetProperties method with instance target. The logic is similar for TypeDescriptor.GetAttributes and TypeDescriptor.GetEvents methods with instance target. Of course, the metadata obtained from the above stages are cached into the IDictionaryService if the instance happens to be a component and its site proffers the dictionary service. This way, unless the cache is invalid, the subsequent call to obtain the metadata can work off the cache. Note that this is a per-instance cache, unlike the per-Type cache used by TypeDescriptor methods that work on Types. The necessity of a per-object cache is explained well in the Remarks section here. To obtain the per-instance cache, call the GetCache on the latest provider. To clear the per-type and the per-object caches call TypeDescriptor.Refresh. Once the caches are cleared, the TypeDescriptor will rebuild all of them on subsequent calls.

We have seen how we can write a TypeDescriptionProvider and a CustomTypeDescriptor for a given target and return any metadata we choose – say a completely different set from what is returned by Reflection. Now, what if someone wants to call some of the lower level Reflection API on the target to get more information about the target? E.g. say the target is object1 and using TypeDescriptor.GetProperties(object1) we get the Pubic, DeclaredOnly and Instance properties of object1. This set of properties is different from the set obtained by object1.GetType().GetProperties() with the above BindingFlags. We have an inconsistency a.k.a. confusion and this is not a happy situation!  To avoid such scenarios, you should use TypeDescriptor.GetReflectionType(object1).GetProperties() with the above BindingFlags. Internally this method will return the System.Type implementation returned by the GetReflectionType call on the object1’s provider. So if you are greatly mucking around with the metadata, make sure your provider’s GetReflectionType returns a System.Type implementation that returns metadata consistent with the provider’s custom type descriptor. This is exactly what happens in the VSD designers where we are actually using a desktop type (e.g. desktop WinForms Button) to represent the corresponding device type (the NETCF Button) on the design surface. We will delve deeper into this in a future post. Also for another illustration, refer to Brian Pepin’s post on designing abstract forms.

As if this much power isn’t enough, the TypeDescriptor.CreateInstance, takes all of the above a step further. CreateInstance first checks if the ServiceProvider (first argument) proffers a TypeDescriptionProvider and if so, it delegates the call to this provider. Else the provider for the target is located the call is delegated to its CreateInstance. The provider can create and return any instance of any other Type (this is called Instance Substitution). Refer to Brian’s post mentioned above to see application of this. Another application of this is in the VSD designers, where we implement a provider that overrides the CreateInstance calls to hook in Type Filtering into the designtime – this is the trick that filters a desktop Type such that on the design surface it appears as the corresponding device (.NETCF) Type.  More about these in the same future post I promised above.

Capabilities of the TypeDescriptor

The purpose of all of the above blah, blah, yada, yada... is so that you can better understand the capabilities of the TypeDescriptor. A great set of documentation on is already provided on MSDN2 that lists and explains all of them – so read it carefully and understand it and let me know if some parts are still not clear. Understanding the TypeDescriptor is critical to understanding my future posts on Designers. To restate, the following are the capabilities of the TypeDescriptor:

Capability Description
Instance substitution Enables an arbitrary type to be created when another type is requested.
Metadata substitution Enables an object's metadata to be modified.
Attribute redirection Enables attributes to be specified dynamically.
Target substitution and shadowing Enables one object to stand in for another.
Extended type descriptor support Enables access to object properties added by other objects.

A simple illustration...

Let us now close this discussion with a small example. It doesn’t do anything useful other than illustrating that you can add your choice of metadata to any given .NET object/Type. We ask TypeDescriptor to register a custom provider the System.Object. And from the above you can see why this provider automatically becomes the provider for all .NET objects and Types. Our custom descriptor than returns a custom type descriptor which when asked for properties, just creates a custom property and returns it along with the original set of properties. Note that both our custom provider and type descriptor selectively override 1 method each and using chaining they delegate the remaining calls to their respective parents.

using System;
using System.ComponentModel;
using System.Collections.Generic;

namespace ExtendWithTD
{
   
class Program
    {
       
static void Main(string[] args)
        {
           
Console.WriteLine("Properties of an arbitrary object: Console.Out:");
           
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(Console.Out);
           
foreach (PropertyDescriptor property in properties) Console.WriteLine("- " + property.Name);

           
Console.WriteLine("\nAdd our useless provider System.Object and chain it with the original one...");
           
TypeDescriptor.AddProvider(new UselessTypeDescriptionProvider(TypeDescriptor.GetProvider(typeof(object))), typeof(object));

           
Console.WriteLine("\nProperties of an arbitrary object: Console.Out:");
            properties
= TypeDescriptor.GetProperties(Console.Out);
           
foreach (PropertyDescriptor property in properties) Console.WriteLine("- " + property.Name);
        }
    }

   
/// <summary>
    /// This is our custom provider. It simply provides a custom type descriptor
    /// and delegates all its other tasks to its parent
    /// </summary>
    internal sealed class UselessTypeDescriptionProvider : TypeDescriptionProvider
    {
       
/// <summary>
   
    /// Constructor
        /// </summary>
        internal UselessTypeDescriptionProvider(TypeDescriptionProvider parent)
            :
base(parent)
        {
        }

       
/// <summary>
        /// Create and return our custom type descriptor and chain it with the original
   
    /// custom type descriptor
   
    /// </summary>
   
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
        {
           
return new UselessCustomTypeDescriptor(base.GetTypeDescriptor(objectType, instance));
        }
    }

   
/// <summary>
    ///
This is our custom type descriptor. It creates a new property and returns it along
   
/// with the original list
   
/// </summary>
   
internal sealed class UselessCustomTypeDescriptor : CustomTypeDescriptor
   
{
       
/// <summary>
        ///
Constructor
       
/// </summary>
       
internal UselessCustomTypeDescriptor(ICustomTypeDescriptor parent)
            :
base(parent)
        {
        }

       
/// <summary>
        /// This method add a new property to the original collection
        /// </summary>
        public override PropertyDescriptorCollection GetProperties()
        {
           
// Enumerate the original set of properties and create our new set with it
   
        PropertyDescriptorCollection originalProperties = base.GetProperties();
           
List<PropertyDescriptor> newProperties = new List<PropertyDescriptor>();
           
foreach (PropertyDescriptor pd in originalProperties) newProperties.Add(pd);

           
// Create a new property and add it to the collection
   
        PropertyDescriptor newProperty = TypeDescriptor.CreateProperty(typeof(object), "UselessProperty", typeof(string));
            newProperties
.Add(newProperty);

           
// Finally return the list
   
        return new PropertyDescriptorCollection(newProperties.ToArray(), true);
        }
    }
}

There is obviously the inconsistency I mentioned above with this example. Ideally, we should implement a System.Type and the custom type descriptor’s GetProperties method should be using our System.Type implementation. But hey! As an exercise, why don’t you come up with the implementation?

Let me know if something isn’t clear from above. I will be glad to explain further...

See you soon in my next post on VSD designers...

Posted by parthopdas | 12 Comments

Writing .NET CF 2.0 Designtime Code – I: An Overview…

Hi Folks...

I am back and it’d have been sooner if not for ELDS :( Never mind that. As many of you have already noted, with Visual Studio 2005 there have been radical changes in the way designtime code is written for .NET Desktop/CF 2.0. These changes in the .NET CF Designtime architecture do break backward compatibility: .NET CF 1.0 Designtime code will refuse to even compile as .NET CF 2.0 Designtime code. But at the same time we believe these changes will:

  1. Improve the experience of the designtime developer. Now you can have designtime and runtime code separated and modularized and your runtime code doesn’t need to have designtime code sprinkled all over it under #ifs.
  2. Better extensibility story. Writing designtime code for Visual Studio 2003/.NET CF 1.0 was a highly complicated and advanced scenario. It was targeted at ISVs to develop designers for the controls they shipped. With the current technology, if someone can write a control, s/he can, with less than or equal effort, write its designer.
  3. Enable better consistency between runtime and designtime. Controls at designtime will look much closer to what they actually look on the device at runtime.
  4. Provide a robust and powerful underlying designtime architecture/framework for you to build great designtime experience for your customers.

Also some of you have asked whether there are any plans for a v1.0 Designtime to v2.0 Designtime upgrade story. There is definitely something up in the air – we have started thinking about it! As of now I do not know exactly how/when it will shape up. But before we release it and so that you are able to take better advantage of the power you wield with .NET 2.0 Designtime, I highly recommend that you take a very detailed pass through Extending Design-Time Support. This is a thorough documentation of .NET 2.0 Designtime, complete with a variety of walkthroughs, samples and lot of other resources. Understanding this is the key to understanding .NET CF 2.0 Designtime. Believe me when I say that the .NET CF 2.0 Designtime is simply built on the .NET 2.0 Designtime. We do nothing special and neither do we get anything special from the .NET Framework Designtime team, just because they happen to sit next door to us :)

There seems to be a little bit of confusion all around on how folks ought to author designtime code for .NET CF 2.0. To help clear this confusion, I am going to temporarily suspend my currently running blog thread on .NET Framework Designtime. I will resume it once I am done laying out some information on how to tackle the .NET CF 2.0 Designtime and the VSD WinForms designer.

I am planning to make divide this series into 3 more posts. Next post will be on designtime assemblies (XMTA/AsmMeta) and why they are critical to the .NET CF 2.0 Designtime. In the post after I am going to build a .NET CF custom control and its designer. And in the last post, I will provide tips on debugging .NET CF 2.0 Designtime code. Let me know if you need me to cover other topics.

See you soon...

Posted by parthopdas | 3 Comments

Generics Terminology in .NET Framework

Hi Folks...

The other day I was investigating an issue that finally boiled down to incorrect usage of System.Reflection & System.Reflection.Emit APIs (SR & SRE hereafter) to analyze Generic types. We were using Type.IsGenericParameter instead of using Type.IsGenericType. During investigation, what made things worse is that each time I went through the first paragraph of their respective help pages, I got more confused. Then I decided to read the Remarks section of the help pages and I was hopelessly lost because it seemed to be written in a dialect of English that I didn’t speak! 

Do you know the difference between Type.IsGenericParameter and Type.IsGenericType? The difference between Generic Type Parameter and Generic Type Argument perhaps? How about Closed Constructed Generic Method and Open Constructed Generic Method? These are a part of some subtle terminology introduced into .NET Framework with Generics. Using SR & SRE without a clear understanding this terminology is only going to land you into trouble. You are going to introduce bugs into your code and you will have a really hard time debugging your own code! Just like me!

It is all there in MSDN but it is highly confusing at the first glance! So I decided to get done with this for good. I spent a good 3 hours going over Generics terminology in .NET Framework in MSDN. This is a gist of my understanding. I am all clear now. You should be too before you begin using SR and SRE.

Basic Terminology

  • Generics:
    • They are classes/structs/interfaces/methods (CSIM hereafter) that have placeholders for one or more of the types they store and/or use.
  • Generic Type:
    • Union of the set of all Generic Type Definitions and Constructed Types.
    • A System.Type object represents a Generic Type iff its IsGenericType property is true
  • Generic Method:
    • Must have a non-empty list of Generic Type Parameters.
    • A method being a Generic Method doesn’t have anything to do with the enclosing type being Generic Type or not
    • Union of the set of all Generic Method Definitions and Constructed Methods.
    • Generic Type Parameters can appear as the return type or as the types of the formal parameters
    • A System.Reflection.MethodInfo object represents a Generic Method iff its IsGenericMethod property is true
  • Generic Type Definition:
    • A CSI declaration that serves as a template, with placeholders for the types it can contain or use.
    • A System.Type object represents a Generic Type Definition iff its IsGenericTypeDefinition property is true
  • Generic Method Definition:
    • A method with two parameter lists: A non-empty list of placeholder types and a list of formal parameters
    • A System.Reflection.MethodInfo object represents a Generic Method Definition iff its IsGenericMethodDefinition property is true
  • Generic Type Parameter:
    • It is the placeholder type in a Generic Type/Method Definition.
    • It is represented using a System.Type object in SR and SRE.
    • A System.Type object represents a Generic Type Parameter iff its IsGenericParameter property is true
    • Example: Is T in Dictionary<T, int> in "class C<T> : Dictionary<T, int>" a Generic Type Parameter? Yes!
  • Generic Type Argument:
    • It is any type that is substituted for a Generic Type Parameter. It could be another Generic Type Parameter.
    • IsGenericParameter is false
    • A System.Type object represents a Generic Type Argument iff its IsGenericParameter property is false
  • Constructed Generic Type/Method:
    • A new type/method constructed as a result of specifying actual types for one or more of the Generic Type Parameters of a Generic Type/Method Definition.
    • Example: Is A<B<, >, > a Constructed Generic Type? Yes!
  • Closed/Open Constructed Generic Type:
    • A Closed Constructed Generic Type is the result of specifying Generic Type Arguments for all Generic Type Parameters of a Generic Type/Method Definition. An Open Constructed Generic Type otherwise.
    • A System.Type object represents a Closed Constructed Generic Type iff its ContainsGenericParameters property is false. Otherwise it is an Open Constructed Generic Type.
    • Only a Closed Constructed Generic Type can be instantiated
    • Is A<B<T, string>, int>.C a Closed Constructed Generic Type? No!
  • Closed/Open Constructed Generic Method:
    • A Closed Constructed Generic Method has no unassigned Generic Type Parameters *and* the containing type is a Closed Constructed Generic Type *and* all the Generic Type Arguments are Closed Constructed Generic Types. An Open Constructed Generic Method otherwise.
    • A System.Reflection.MethodInfo object represents a Closed Constructed Generic Method iff its ContainsGenericParameters property is false. Otherwise it is an Open Constructed Generic Method
  • Constraints:
    • They are limits placed on Generic Type Parameters.
    • The GenericParameterAttributes property of a System.Type object representing a Generic Type Parameter gets a combination of System.Reflection.GenericParameterAttributes flags that describe its covariance and special constraints
    • The GetGenericParameterConstraints() method of a System.Type object representing a Generic Type Parameter returns an array of System.Type objects that represent its constraints.

A few points to note

  • If a nested types doesn't have Generic Type Parameters of its own, the enclosing type determines the above for it.
  • Generic Type Parameters and Generic Type Arguments have the same relation as the parameters and arguments of a function.
  • typeof(Dictionary<, >).MakeArrayType() returns a System.Type object that is not a Generic Type but is an Open Constructed Generic Type. Same for pointers
  • In SR & SRE:
    • Generic Type Parameters are represented by System.Type
    • A Type/MethodInfo object representing a Generic Type/Method has an array of types containing the Generic Type Parameters and Generic Type Arguments

Examples to consolidate our understanding

Consider the followign code snippet. The invariant conditions are shown in the comments below it.

public class Base<T, U>
{
    public static T M1Base(U u) { return default(T); }
}

public
class Derived<V> : Base<string, V>
{
    public G<Derived<V>> F;
   
    public
class Nested
    {
        void M1Nested() { }
    }
   
    public
static void M1Derived<W>() { }
}

public
class G<T> { }

/*
Type: Derived<V> 
                 IsGenericType: True
       IsGenericTypeDefinition: True
     ContainsGenericParameters: True
            IsGenericParameter: False

Type: Base<string, V>
                 IsGenericType: True
       IsGenericTypeDefinition: False
     ContainsGenericParameters: True
            IsGenericParameter: False

Type: Array of Derived<int>
                 IsGenericType: False
       IsGenericTypeDefinition: False
     ContainsGenericParameters: False
            IsGenericParameter: False

Type: Type parameter T in Base<T>
                 IsGenericType: False
       IsGenericTypeDefinition: False
     ContainsGenericParameters: True
IsGenericParameter: True

Type: Field Derived<V>.F
                 IsGenericType: True
       IsGenericTypeDefinition: False
     ContainsGenericParameters: True
IsGenericParameter: False

Type: Nested
                 IsGenericType: True
       IsGenericTypeDefinition: True
     ContainsGenericParameters: True
            IsGenericParameter: False

Method: T Base<T, U>.M1Base(U u)
               IsGenericMethod: False
     IsGenericMethodDefinition: False
     ContainsGenericParameters: True

Method: void Derived<V>.M1Derived<W>()
               IsGenericMethod: True
     IsGenericMethodDefinition: True
     ContainsGenericParameters: True

Method: void Derived<V>.M1Derived<int>();
               IsGenericMethod: True
     IsGenericMethodDefinition: False
     ContainsGenericParameters: True

Method: void Derived<string>.M1Derived<int>()
               IsGenericMethod: True
     IsGenericMethodDefinition: False
     ContainsGenericParameters: False
*/

Some of the System.Reflection API for Generics

  • System.Type.*Generic* members:
    • [P] ContainsGenericParameters: True if the type is an Open Constructed Generic Type. False otherwise. 
    • [P] GenericParameterAttributes: Gets a combination of System.Reflection.GenericParameterAttributes flags that describe the covariance and special Constraints of a Generic Type Parameter
    • [P] GenericParameterPosition: Gets the position of the Generic Type Parameter in the Generic Type Parameter list of the Generic Type/Method that declared the parameter. 
    • [P] IsGenericParameter: True if the type represents a Generic Type Parameter. False otherwise. 
    • [P] IsGenericType: True if the type represents a Generic Type. False otherwise. 
    • [P] IsGenericTypeDefinition: True if the type represents a Generic Type Definition. False otherwise. 
    • [M] GetGenericArguments: Get the array of types representing Generic Type Parameter/Arguments of the type.
    • [M] GetGenericParameterConstraints: Returns an array of System.Type objects that represent the Constraints of a Generic Type
    • [M] GetGenericTypeDefinition: Gets the Generic Type Definition corresponding to the Generic Type.
    • [M] MakeGenericType: Construct Closed/Open Constructed Generic Type from the Generic Type Definition
  • System.Reflection.MethodInfo.*Generic* members:
    • [P] ContainsGenericParameters: True if the type is an Open Constructed Generic Method. False otherwise.
    • [P] IsGenericMethod: True if the MethodInfo represents a Generic Method. False otherwise.  
    • [P] IsGenericMethodDefinition: True if the MethodInfo represents a Generic Method Definition. False otherwise.  
    • [M] GetGenericArguments: Get the array of types representing Generic Type Parameter/Arguments of the MethodInfo
    • [M] GetGenericMethodDefinition: Gets the Generic Method Definition corresponding to the Generic Method
    • [M] MakeGenericMethod: Construct Closed/Open Constructed Generic Method from the Generic Method Definition

References

If you want to learn more about Reflection & Generics in .NET Framework here are some references:

Finally as an exercise:

Type.IsGenericType Property help page contains an error in the Example-Invariants table. Armed with the above knowledge find it out and let me know! :)

That's all for now... See you in my next post!

.NET Framework Designtime – I: An Introduction...

Hi Folks...

For a while now, I have been studying the .NET Framework Designtime Infrastructure. Not only because I now own the VSD WinForms and Data designers. But also because the design & architecture of this piece is quiet fascinating… What is the .NET Framework Designtime Infrastructure.? It is the guts of the Visual Studio designer that lets you rapidly design and build rich Windows Forms UI.

In this series, I will dump my understanding of the .NET Framework Designtime. We will also progressively build an application that can design Windows Installer UI. Our application will also persist the UI in a Windows Installer XML Source file (.wxs) that you can readily use in your WiX projects. The first part of the series will be an introduction to the .NET Framework Designtime. Nothing much explained but a lot outlined. So here goes…

First off...

The term designer used here is not the same as VS WinForms Designer that you see when you create a new windows application. What you see is really the design surface provided by VS acting as the designer host.

Earlier, in the MFC/ActiveX worlds, the logic for designtime behavior of a component was hardcoded into the tool (a.k.a. IDE) that provided the design surface – meaning, it was the IDE and not the MFC/ActiveX component that was responsible for providing its (the component’s) designtime behavior. This also meant that different IDEs offered their own designtime environments for components, and with different user interfaces and capabilities. And since an IDEs fixed feature set cannot account for the needs of all components, ActiveX/MFC components had only a limited level of custom designtime support.

In .NET Framework world though, the framework provides every component with its own runtime (obviously!) and designtime behaviors. And just like how the runtime behavior of a component can be customized/extended (e.g. subclassing), so can the designtime behavior of the component be customized & extended by IDEs. This means that every .NET Framework component contains logic for how it behaves and runtime and at designtime. The IDE simply extends, configures and exposes this designtime behavior to the developer. There are of course some services and behaviors that are very strongly tied to the IDE that hosts the design surface (e.g. exposing the design surface, context menus, toolbox interaction etc.). These services are implemented by the host IDE and the component uses these services at designtime after obtaining them from the host IDE through well defined interfaces.

Comparing MFC/ActiveX & .NET Framework Designtime: Click to enlarge

Designtime Runtime code seperation...

Of course when I say that every component provides both its runtime and designtime behavior, I don’t mean that every component needs to contain the code for its designtime behavior and the code for its runtime behavior in the same class or even the same assembly. Although this is possible, in most cases it is not practical. Doing so would simply bloat the runtime code which necessarily needs to be as slim and trim as possible. Note that every byte loaded into memory has a cost associated with it (working set, time to JIT etc.). As an example, consider System.Windows.Forms.Control. Its runtime code is in System.Windows.Forms.Control, System.Windows.Forms.dll and its designtime code in System.Windows.Forms.Design.ControlDesigner, System.Design.dll. Use Reflector to peek into the implementations of both and you will get an idea of the bloat. Just going by lines of code Control.cs is 19217 lines and ControlDesigner.cs is 3842 lines which is ~20% code bloat.

So more often than not, designtime and runtime code separation is employed. This basically means that the designtime code is located on a different class/assembly than the runtime code, like in the System.Windows.Forms.Control example. And the runtime code provides pointers to the designtime code using one or more attributes (e.g. DesignerAttribute). At designtime the .NET Designtime Infrastructure then just looks up the designtime attributes on the component, locates and executes the designtime code to allow us to design the component.

Things get a little bit trickier when you are designing .NET CF components. The .NET CF usually executes on memory constrained devices so it needs to be highly trimmed. Since attributes contribute to size of metadata and therefore overall size of the assembly, the usage of attributes in .NET CF code cannot be as lavish as that on the desktop. Because of this the .NET CF doesn’t support any of the designtime attributes. To work around this the VSD WinForms designers uses the XMTA and AsmMeta files. I will elaborate on the XMTA/AsmMeta files in a future blog but for now, in short, the pointers to the designtime code reside in the AsmMeta assemblies. So at designtime for a .NET CF component, the VSD WinForms designer locates the AsmMeta assembly for the component, reads the pointer to the designtime code from it, loads and executed the designtime code to allow us to design the .NET CF component.

An overview of the designtime infrastructure...

How do you typically use the IDE to design a windows forms application? For starters, you create a class that derivers from Form (or UserControl or Component). Then you open that class in design view and drag-n-drop other controls and/or components on it, edit the various properties and hook up handlers for the various events. While you are designing the application the IDE may look like the following:

Design surface items: Click to enlarge

As usual, the details hidden from the user are a lot more complicated. The following diagram will give you an idea of what is actually going on under the hood. A sound understanding of the pieces in the diagram is the key to understanding the .NET Framework Designtime Infrastructure. In this series I will be explaining each of these pieces.

Designtime Environment: Click to enlarge

How and where does the VSD WinForms designer fit in?

In the case of the desktop .NET Framework both designtime and runtime code is executed by the desktop CLR. But for .NET CF, the designtime code is executed by the desktop CLR (hosted inside Visual Studio) while the runtime code is executed by the device CLR. This implies that for .NET CF components the designtime code targets the desktop .NET Framework while the runtime code targets the .NET CF.

Also the architecture of .NET Designtime is such that during designtime the .NET Framework components (well controls really!) draw themselves! Meaning at designtime, in addition to the component's designtime code, its runtime code is also executing! Meaning during designtime, since Visual Studio has loaded only the desktop CLR, device controls that require the device CLR cannot run! All device components belong to the following two categories:

  1. Retargetable: On the desktop when you try and load a retargettable assembly (e.g. System.WinForms.dll), the desktop fusion will load the corresponding desktop assembly automatically
  2. Desktop Incompatible: Assemblies referring directly or indirectly to platform specific drawing/rendering code (e.g. through P/Invoke) For both above cases, you are forced to use the desktop components during design time!

The above is the basis for the .NET CF Designtime.

Moreover the set of Properties/Attributes/Events exposed by a .NET CF component is usually, but not always, a subset of the set exposed by the corresponding desktop .NET component. This needs to be reflected during the designtime – we cannot show a desktop only P/A/E while designing a .NET CF component. To achieve this VSD WinForms designer uses the XMTA/AsmMeta trick that is based on the P/A/E filtering natively supported by the .NET 2.0 designtime.

Central to the P/A/E filtering architecture is the TypeDescriptor. The v2.0 .NET designtime doesn’t use System.Reflection to obtain a component’s metadata. Instead the TypeDescriptor is used. Using it, you can remove all of the components native metadata (ones that you get by System.Reflection) and replace them with your choice of metadata! More on this in a subsequent post…

Thats all this post. Next post will dig deeper into the Designtime Environment diagram and start constructing our WiX UI designer.

See you later...

Posted by parthopdas | 10 Comments

Object Test Bench – IV: Please send us your feedback and vNext wish list...

Hi Folks…

It’s been a long long time since my last post. What have I been doing since then? Hmmm… apart from ELDS here is that list:

  1. Transitioned out of J#: Handed over my owner ship of J# Project system, Object Test Bench and other areas.
  2. Started on transitioning into VSD: Had a few meetings with Carlton.
  3. Got married to Anutthara and went for a 2 week post marriage vacation.
  4. Finished transitioning into VSD after numerous meetings with Xin, Carlton, Andrew and Brian Chamberlin: I now own the VSD Data designers, WinForms Designers and some parts of managed VSD IDE.
  5. Got rammed down by a spate of VSD bugs, wrestled with them hard and finally prevailed. We are now ready to ship Visual Studio 2005.

But these are of course very poor excuses for not coming up with a single post in 6 months. But I am going to change that esp. since engaging and spending time with you guys is one of the focus points for my next and future career reviews :-)

Getting back to the topic on hand…

Object Test Bench has been out for many months now. The final release will have very few changes from Beta 2. And we are looking forward to enhancing it for v2. Here is your chance to shape the v2 of Object Test Bench.

How have you liked OTB so far? What is the weirdest way you have used it? Which feature of OTB did you hate the most? What are the roadblocks you have hit? What enhancements would you like us to make in v2? What do you think it will take for OTB to be a killer component?

Personally, I would like to see the following in v2.

  1. Support for Generics
  2. Enhanced integration with the debugger (e.g. edit and continue and support for native C++)
  3. Built in support for Unit Testing

Basically OTB should graduate to a full blown feature helping in enterprise software development. But note that I am no longer in the team that owns OTB, so you should not be surprised if OTB v2 turns our completely different from what I think it should :-)

We are eagerly waiting for your feedback, criticisms, comments and ideas for v2. You may send them through any of the channels below:

  1. Make a suggestion or repro a bug on MSDN Product Feedback Center
  2. Send a mail to JSharp Feedback
  3. Contact and/or reply to the team members’ blogs (Brian Keller, Varun Gupta, Gaurav Seth, Jaiprakash Sharma)
  4. You may email your suggestions/bug directly to our product manager, Brian Keller
  5. Post your feedback and feature requests on the Visual J# Forum
  6. Make a post on the J# public newsgroup at microsoft.public.dotnet.vjsharp

Last but not the least you may contact me and I will personally go and deliver your message to the J# team. (They are sitting just next door to me anyways :-)

See you in the next post…

Posted by parthopdas | 4 Comments
Filed under:

Object Test Bench – III: Exploring Framework APIs...

Hi Folks…

How often have you surfed the web, wanting to learn about a new whiz-bang .NET Framework API that you just heard of? Often right? I for one have found myself do this very frequently…

Surfing the web usually comprises of running a web search on the whiz-bang keywords that got you in the mood in the first place. With a bit of luck, the search engine returns a host of sites that contain documentations/tutorials/samples/snippets on the API you are looking for. There are sites like The Code Project, DevX.com, DevHood that are doing a great job in introducing the API to audiences at all levels. Then there also sites like the one you are currently on – the blogs. After reading the documentation/comments on these sites you aren’t really done till you actually try out the code snippets/samples – right?

Here is when OTB can help you out! You no longer need to copy the sample, build it and then debug it before you can get a grip on what’s the API is really about. With as little work as starting the IDE and creating a Zero Impact project, OTB will help you understand the API visually. This is what I am going to show you today. And note that, the API need not really be an .NET Framework API. It could be any 3rd party API written for the .NET platform.

Searching on the web for Reflection.Emit…

One of the killer features that .NET Framework offers the compiler writers is the Reflection.Emit namespace. Now I want to learn about that. So I run a web search with “Reflection.Emit dynamically generated code”. And the first hit on one of the popular search engines is an excellent blog by my fellow Microsoftie, Mike Stall. That’s a good hit – apart from demonstrating how to generate code dynamically, Mike also demonstrates how to debug the dynamic code!!! Ain’t that really totally cool!!!

So what do we do next?
1.    Open launch Visual Studio 2005
2.    Create a Zero Impact project (I am creating a C# console application – you could create either that or any of the C#/J#/VB projects).
3.    Save this text file on your hard disk (say C:\temp\souces.txt)
4.    Open C:\temp\source.txt in VS and set a break point in the second line (i.e. the line with “xyz = "hello";”)
5.    Turn of Tools::Options::Debugging::General::Enable Just My Code (Managed only)
/*01*/  // Sample of emitting debugging information for dynamic modules
/*02*/  // Reflection emit example adopted from http://blogs.msdn.com/joelpob/archive/2004/01/21/61411.aspx
/*03*/  using System;
/*04*/  using System.Reflection;
/*05*/  using System.Reflection.Emit;
/*06*/  using System.Threading;
/*07*/  using System.Diagnostics.SymbolStore;
/*08*/ 
/*09*/  public class EmitHelloWorld
/*10*/  {
/*11*/      static void Main(string[] args)
/*12*/      {
/*13*/          // create a dynamic assembly and module
/*14*/          AssemblyName assemblyName = new AssemblyName("HelloWorld");
/*15*/ 
/*16*/          AppDomain appDomain = Thread.GetDomain();
/*17*/          AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
/*18*/ 
/*19*/          ModuleBuilder module = assemblyBuilder.DefineDynamicModule("HelloWorld.exe", true); // <-- pass 'true' to track debug info.
/*20*/ 
/*21*/          // Tell Emit about the source file that we want to associate this with.
/*22*/          Guid emptyGuid;
/*23*/          emptyGuid = Guid.Empty;
/*24*/          ISymbolDocumentWriter doc = module.DefineDocument("Source.txt", emptyGuid, emptyGuid, emptyGuid);
/*25*/ 
/*26*/          // create a new type to hold our Main method
/*27*/          TypeAttributes typeAttributes;
/*28*/          typeAttributes = TypeAttributes.Public | TypeAttributes.Class;
/*29*/          TypeBuilder typeBuilder = module.DefineType("HelloWorldType", typeAttributes);
/*30*/ 
/*31*/          // create the Main(string[] args) method
/*32*/          MethodAttributes methodAttributes;
/*33*/          methodAttributes = MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public;
/*34*/          Type voidType = Type.GetType("System.Void");
/*35*/          Type[] parameterTypes;
/*36*/          parameterTypes = new Type[] { typeof(string[]) };
/*37*/          MethodBuilder methodbuilder = typeBuilder.DefineMethod("Main", methodAttributes, voidType, parameterTypes);
/*38*/ 
/*39*/          // generate the IL for the Main method
/*40*/          ILGenerator ilGenerator = methodbuilder.GetILGenerator();
/*41*/          OpCode genericOpCode;
/*42*/ 
/*43*/          // Create a local variable of type string, and call it xyz
/*44*/          Type stringType = Type.GetType("System.String");
/*45*/          LocalBuilder localXYZ = ilGenerator.DeclareLocal(stringType);
/*46*/          localXYZ.SetLocalSymInfo("xyz"); // Provide name for the debugger.
/*47*/ 
/*48*/          // Emit sequence point before the IL instructions. This is start line, start col, end line, end column,
/*49*/ 
/*50*/          // Line 2: xyz = "hello";
/*51*/          ilGenerator.MarkSequencePoint(doc, 2, 1, 2, 100);
/*52*/          genericOpCode = OpCodes.Ldstr;
/*53*/          ilGenerator.Emit(genericOpCode, "Hello world!");
/*54*/          genericOpCode = OpCodes.Stloc;
/*55*/          ilGenerator.Emit(genericOpCode, localXYZ);
/*56*/ 
/*57*/          // Line 3: Write(xyz);
/*58*/          Type sysConsoleType = Type.GetType("System.Console");
/*59*/          parameterTypes[0] = typeof(string);
/*60*/          MethodInfo infoWriteLine = sysConsoleType.GetMethod("WriteLine", parameterTypes);
/*61*/          ilGenerator.MarkSequencePoint(doc, 3, 1, 3, 100);
/*62*/          genericOpCode = OpCodes.Ldloc;
/*63*/          ilGenerator.Emit(genericOpCode, localXYZ);
/*64*/          genericOpCode = OpCodes.Call;
/*65*/          ilGenerator.EmitCall(genericOpCode, infoWriteLine, null);
/*66*/ 
/*67*/          // Line 4: return;
/*68*/          ilGenerator.MarkSequencePoint(doc, 4, 1, 4, 100);
/*69*/          genericOpCode = OpCodes.Ret;
/*70*/          ilGenerator.Emit(genericOpCode);
/*71*/ 
/*72*/          // bake it
/*73*/          Type helloWorldType = typeBuilder.CreateType();
/*74*/ 
/*75*/          // run it
/*76*/          MethodInfo mainMethod = helloWorldType.GetMethod("Main");
/*77*/          object[] parameters;
/*78*/          parameters = new string[] { null };
/*79*/          mainMethod.Invoke(null, parameters);
/*80*/ 
/*81*/          // set the entry point for the application and save it
/*82*/          assemblyBuilder.SetEntryPoint(methodbuilder, PEFileKinds.ConsoleApplication);
/*83*/          assemblyBuilder.Save("HelloWorld.exe");
/*84*/      }
/*85*/  }

For ready reference above is the source code from Mike’s blog, that we are going to study visually. Here we go!

Doing it… Visually!

This section assumes that you know your way around Object Test Bench. If not, please go through my previous blog and/or keep it open for reference. 

(Line 14) In the CV, navigate to System.Reflection.AssemblyName. Right click and from the CI menu, select the constructor with a string parameter. The CI dialog will appear. Enter assemblyName as the instance name and "HelloWorld" as parameter and press OK. You will then have the assemblyName object on the test bench. Go ahead and explore it using the enhanced datatips.

(Line 16) In the CV, invoke the GetDomain static method on the System.Threading.Thread class. In the MCR dialog that comes up, save the return value on the test bench as appDomain. In the test bench, right click on appDomain and invoke the DefineDynamicAssembly method on it with assemblyName and System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave as parameters. Using the MCR, save the return value as assemblyBuilder.

(Line 19) Invoke the DefineDynamicModule method on the assemblyBuilder object with "HelloWorld.exe" and true as parameters. Save the return value as module.

(Line 22) Create the emptyGuid object by executing “Guid emptyGuid;” in IW. Note that emptyGuid is already set to System.Guid.Empty. Invoke the DefineDocument method on the module object with "Source.txt" as the first parameter. For the remaining 3 parameters select emptyGuid from the parameter dropdown list. Save the return value as doc.

(Line 27) Create the typeAttributes object by executing “System.Reflection.TypeAttributes typeAttributes;” in the IW. In the test bench, hover over the typeAttributes object to get the enhanced datatips. Using the enhanced datatips and set the value of typeAttributes to “System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Class”. Invoke the DefineType method on the module object with "HelloWorldType" and typeAttributes as parameters. Save the return value as typeBuilder.

(Line 32) Create the methodAttributes object by executing “System.Reflection.MethodAttributes methodAttributes;” in the IW. Using the enhanced datatips, set methodAttributes to “System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.Static | System.Reflection.MethodAttributes.Public”. Invoke the GetType static method on the System.Type class with "System.Void" as parameter. Save the return value as voidType. Create the parameterTypes object by executing “Type[] parameterTypes;” in the IW. Using the enhanced datatips, set parameterTypes to “new Type[] { typeof(string[]) }”. Invoke the DefineMethod on typeBuilder with "Main", methodAttributes, voidType, parameterTypes as parameters. Save the return value as methodbuilder.

(Line 40) Invoke the GetILGenerator method on the methodbuilder object. Save the return value as ilGenerator. Create the genericOpCode object by executing “System.Reflection.Emit.OpCode genericOpCode;” in the IW.

(Line 44) Invoke the GetType static method on the System.Type class with "System.String" as parameter. Save the return value as stringType.  Invoke the DeclareLocal method on the ilGenerator object with stringType as parameter.   Save the return value as localXYZ. Invoke the SetLocalSymInfo method on the localXYZ object with "xyz" as parameter.

(Line 51) Invoke the MarkSequencePoint method on the ilGenerator object with doc, 2, 1, 2, 100 as parameters. Using the enhanced datatips, set genericOpCode to System.Reflection.Emit.OpCodes.Ldstr (Important: Please see the notes section below!). Invoke the Emit method on the ilGenerator object with genericOpCode and "Hello world!" as parameters. Using the enhanced datatips, set genericOpCode to System.Reflection.Emit.OpCodes.Stloc. Invoke the Emit method on the ilGenerator object with genericOpCode and localXYZ as parameters.

(Line 58) Invoke the GetType static method on the System.Type class with "System.Console" as parameter. Save the return value as sysConsoleType. Using the enhanced datatips, parameterTypes[0] to typeof(string). Invoke the GetMethod method on the sysConsoleType object with "WriteLine", parameterTypes as parameters. Save the return value as infoWriteLine. Invoke the MarkSequencePoint method on the ilGenerator object with doc, 3, 1, 3, 100 as parameters. Using the enhanced datatips, set genericOpCode to System.Reflection.Emit.OpCodes.Ldloc. Invoke the Emit method on the ilGenerator object with genericOpCode and localXYZ as parameters. Using the enhanced datatips, set genericOpCode to System.Reflection.Emit.OpCodes.Call. Invoke the EmitCall method on the ilGenerator object with genericOpCode, infoWriteLine, null as parameters.

(Line 68) Invoke the MarkSequencePoint method on the ilGenerator object with doc, 4, 1, 4, 100 as parameters. Using the enhanced datatips, set genericOpCode to System.Reflection.Emit.OpCodes.Ret. Invoke the Emit method on the ilGenerator object with genericOpCode as parameter.

(Line 73) Invoke the CreateType method on the typeBuilder object. Save the return value as helloWorldType.

(Line 76) Invoke the GetMethod method on the helloWorldType object with "Main" as parameter. Save the return value as mainMethod. Create the parameters object by executing “object[] parameters;” in the IW. Using the enhanced datatips, set parameters to “new string[] { null }”. Invoke the Invoke method on the mainMethod object with null, parameters as arguments.

Yooooohooooo!!! #1: At this point the break point in source.txt that you had set earlier should be hit. (Here is how it looks on my machine) On you step out of the Sources.txt file, you will get the MCR dialog informing you that the call was successful. (Here is how my IDE looks at this point)

(Line 82) Invoke the SetEntryPoint method on the assemblyBuilder object with methodbuilder, System.Reflection.Emit.PEFileKinds.ConsoleApplication as parameters. Invoke the Save method on the assemblyBuilder object with "HelloWorld.exe" as parameter.

Yooooohooooo!!! #2: If you go and examine the project output directory, you can see HelloWorld.exe and HelloWorld.pdb sitting. What’s more, you can open HelloWorld.exe as a project and on pressing F11, the control will step into Sources.txt.

So what have we learnt!

A lot about Reflection.Emit? Yes of course! But learning Reflection.Emit isn’t the point I am trying to make with this blog. In this blog I have outlined a generic procedure that you employ to visually study and explore any 3rd party API for the .NET platform. Just like the Class Designer helps you get a static view of the API you are studying using, OTB helps you get the dynamic view of that API.

Notes:

Because of a bug in Visual Studio 2005 Beta 2, it will not be possible to set genericOpCode directly to System.Reflection.Emit.OpCodes.Ldstr using the enhanced datatips. As a work around you can set genericOpCode to ( System.Reflection.Emit.OpCode )Type.GetType( "System.Reflection.Emit.OpCodes" ).GetField( "Ldstr" ).GetValue( null ) using the enhanced datatips. This bug has been fixed in the post Beta 2 builds. So you can use the direct method in Visual Studio 2005 RTM.

(To be concluded...)

Posted by parthopdas | 249 Comments
Filed under:

Object Test Bench – II: A User’s Manual…

Hi folks…

This blog was due a long time back… I haven’t been able to get down to it so far because of multiple reasons, first of which is that I suffer from a chronic case of ELDS: Extreme Laziness Disorder Syndrome :-). Second, I have just moved into a new team – Visual Studio for Devices. I have been busy doing the transition work and oh boy, there is still a lot to be done!

Third reason, a genuine one, is that I have been wondering about the format of this blog. Since this is a User’s Manual, obviously there needs to be lot of pictures and illustrations. But too many of them will make the blog too big to sit through! At this point I came across the WinkTM. This is a fantastic tool for creating animated illustrations. All SWF tutorials in this blog are created using that tool, except the sections with the enhanced datatips. Satish – great job and thanks!

In this blog, I will take you through the various features of OTB. The  image in each section points to an animated tutorial for that section. Please note this blog is not the official OTB documentation. The official document is here.

Getting started:

OTB can be accessed in the VS IDE as follows:
1.    Class View (CV): From the context menu of a supported CodeType, you can create instances of the CodeType as well as invoke its static methods.
2.    Class Designer (CD): From the context menu of a shape for a supported CodeType, you can create its instance and invoke its static methods.
3.    OTB Tool Window: Once an instance of a CodeType is created, a shape representing the instance is available on the tool window. From the context menu of the shape, you can invoke methods on the object. You can also remove the object from test bench.

The above context menus are populated dynamically with the constructors, static and instance methods for each CodeType/object. The methods inherited by the CodeType from its parent hierarchy appear in the Inherited Methods group. Also only methods/constructors that conform to certain restrictions appear on the context menus. Here is an example.

Create Instance:

Right click on a CodeType in the CV or CD to obtain the context menu. For each CodeType recognized by OTB, a Create Instance submenu will be available on the context menu, if the CodeType has at least one constructor recognized by OTB.

On clicking on one of the menu items, OTB will display a dialog like the following:

Click to view the full size image...

You can then enter the values of each parameter that you want to pass to the method in the parameter entry grid. For primitive types, you can type in arbitrary values (e.g. for a string, you can enter any arbitrary string in the value cell). For both primitive and non-primitive types, the dropdown in the value cell lists the available values. The available values consist of the following:

·         Default values, if any. (E.g. default values for Boolean are false and true. For an enum type, the default values are all the defined enumerations)

·         At most 5 most recently used values for primitive types.

·         All objects in the test bench whose types are the same as the parameter type or a subtype of the parameter type.

Click to view the full size image...

Once you are done entering all the parameters, press OK and barring any failures/exceptions, you should have an object on the test bench.

A CodeType is not recognized by OTB if it doesn’t meet these conditions. E.g. OTB v1 does not recognize generic types. You will not be able to use OTB features on unrecognized CodeTypes. Although that you can create instances of most classes and structs, you cannot create instances of abstract classes, arrays, delegates, interfaces, enums etc.

A constructor is recognized by OTB subject to these conditions. OTB will not display or invoke constructors that it cannot recognize.

Invoke Static Methods:

The CV/CD context menu for a recognized CodeType will also include the Invoke Static Method submenu. This menu lists all the static methods of the CodeType, subject to these restrictions. The static methods inherited from the parent hierarchy are grouped under Inherited Methods submenu. CodeTypes are recognized subject to the same conditions described in the Create Instance section above.

Clicking on one of the items in the Invoke Static Method menu will throw up a dialog box similar to the Create Instance dialog box, except that the Name field will not be present. After entering the parameters and press OK and OTB will invoke the method for you and return the result to you as described in the Method Call Result section below.

Invoke Instance Methods:

Right clicking on an object on the test bench will bring up the Invoke Method submenu. This menu lists all the methods that can be invoked on the object, subject to these restrictions. The methods inherited from the parent class are listed under the Inherited Methods menu. For J# and VB, this list of methods includes the static methods of the CodeType also. For C# the methods listed are the instance methods only.

The test bench can contain objects are actually references to arrays, interfaces, abstract classes, enums and delegates apart from classes and structs. You can invoke methods on any of these.

To invoke one of the instance methods, click on the respective item in the Invoke Method menu and follow the procedure described in the Invoke Static Method section.

Method Call Result:

Assuming there are no errors/failures after you invoke a method (static or instance), there are two cases. First, if the return type of the method is void, a dialog will be shown informing you that the method call succeeded. Optionally you can choose to reinvoke the method with different parameters by clicking Retry.

If the return type of the method is not void, following dialog box will be thrown up:

Click to view the full size image...

At this point you can choose to save the return value onto the test bench. You can also choose to reinvoke this method with different parameters by clicking Retry. On clicking Retry, you will be presented with the method invoke dialog as described in the Invoke Method sections above.

Inspect/Modify Objects on the Test Bench:

Once an object is added to the test bench, hovering over it will bring up the Enhanced Datatip.

Click to view the full size image...

The enhanced datatip allows you to navigate the entire object – all fields, properties, entire parent hierarchy right up to System.Object by just hovering. Apart from navigating the entire object, you can also change/edit the read/write fields & properties.

The enhanced datatips also give you access to the customized display of objects using the Debugger Visualizers.

Step Through Code in Break Mode:

This is useful when you have written a utility function that has especially convoluted algorithm (E.g. generating CRC for a given block of data)… Now once you have finished implementing the algorithm in a GenerateCRC32 function, you would like to perform some unit tests. You then typically invoke this method using OTB as described above.

Now what happens when you see that the method call result is not what you expected? The first instinct is to place a breakpoint and step through the code right? But wait, don’t F5 yet!

Instead place a breakpoint at the relevant point inside GenerateCRC32 and then invoke this using OTB. Once you have entered the required parameters and pressed OK in the Invoke Method dialog, OTB asks the debugger to evaluate GenerateCRC32. Note that we are still in the design mode when the debugger starts evaluating GenerateCRC32 under the hood.

Now when this under–the–hood–execution hits the breakpoint, the debugger enters break mode and you will see that the function evaluation has been suspended at the breakpoint. Now you are *completely* in break mode – you can use the autos/locals windows; do step–in/step–over/step–out; use (quick)watch windows and all other IDE features that you normally use while stepping through. It is as if you had pressed F5/F10/F11 initially and entered directly into GenerateCRC32. Note that for the usual F5/F10/F11 process you have to write a driver code for you utility method, step through the driver code and then finally reach and step through GenerateCRC32. Essentially, you are doing F1/F10/F11 on any arbitrary function without having to write driver code.

Once you are done stepping through GenerateCRC32 you can simply hit a F5 and the debugger will reenter the design mode (Note: design mode not run mode), wait for the function evaluation to complete, return the method’s return value to OTB. Finally OTB will display the result as described in the Method Call Result section above.

I hereby dub thee Design–Mode–Debugging! :-)

Immediate Window Interaction:

One way to look at OTB is that it is an intelligent GUI over the Immediate Window (IW). Whatever you do using OTB you can also do using the IW (albeit you don’t have the features described in the above sections). So if you declare an integer using “int i = 0;” in the IW, the integer “i” will appear in the test bench. Subsequently if you change the value of “i” or even delete “i”, these operations will get reflected on the test bench.

What’s more, every operation performed by OTB is logged into the command window as statements in the language of the project you are working on. You can save this sequence of statements and later on execute them one by one in the IW to recreate your session.

But there are certain cases in which you would want to use the IW because OTB doesn’t provide a way out. Remember that I had earlier mentioned earlier that using Create Instance UI you cannot create instances of abstract classes, arrays, delegates, interfaces, enums etc.? Well using IW you can get around most of this limitation. You get instances of arrays, delegates and enums on the test bench by simply executing their constructor statements in the IW. E.g. “string[] stringArray = new string[] { "1", "2" };”. For abstract classes and interfaces you can get their null instances on the test bench by simply executing their declaration statements. E.g. “IAppDomainSetup appDomainSetup;”.

Now you might ask: Using the IW, can I trick OTB into adding instances of instantiated generic classes? Unfortunately no! An object of any CodeType that OTB doesn’t recognize will not be added to the test bench, although it is possible to create such objects and use them from the IW. What this means that if you evaluate “List<int> intList = new List<int>();”, the object “intList” will be created and you can invoke methods on it from the IW. But “intList” will not be added to the test bench and OTB cannot operate on “intList”.

OTB Sessions and Out–of–Date Projects:

An important scenario is when you have created a lot of objects on the test bench and then for some reason you need to make a minor change to the code before you can create the next object or invoke the next method. What happens then?

Technically, once you have recompiled the code, the new assembly generated and classes in it are completely different from the ones in the previous built even though you may not have made any code changes. Extending this, once you have objects on the test bench and then you make some changes to the code, the objects aren’t really valid. They are from classes that have been discarded. Basically you cannot invoke methods on the new classes/objects using objects from the discarded classes.

So in the scenario above, once there are changes in the project that require a rebuild, OTB will prevent you from performing the next operation without a rebuild. You can choose to rebuild the project in which case the test bench will be cleared. Alternatively you can continue to inspect and modify the objects on the test bench using the enhanced datatips.

Handling Errors/Failures/Unhandled–Exceptions:  

In case of failures that occur while OTB is performing some operation, OTB will abort the current operation and report a diagnostic message about the failure. These failures include build breaks, unhandled–exceptions and other general failures. In case of unhandled–exceptions the diagnostic message will be the exception’s text message. Once presented with the error, you can take the corrective measures and retry the operation.

 

Whew! That pretty much describes what you can do using OTB. Next blog in this series will illustrate some real life use–cases. See you then…

(To be continued…)

 

Posted by parthopdas | 4 Comments
Filed under:

Visual J# on MSDN TV

Hi everyone,

I have been busy lately for a couple of reasons at least... One of them is the hectic schedule in the Whidbey Beta 2 end game. The other is that I am moving over to a new team – so I am in the process of transitioning out/into my current/next team... Very exciting time, really!

Meanwhile we have some new stuff for J# users... Recently, Pratap Lakshman (the cool dude, J# Lead PM) has been on MSDN TV with a lot of cool info on J#...

Please go through his video and do send us your feedback...

See you later...

Posted by parthopdas | 2 Comments
Filed under:

Object Test Bench – I: Debugging unplugged!!!

Hi folks…

 

As you may have seen from the various blogs and articles floating around on the internet, Visual Studio 2005 will ship with a new feature called the Object Test Bench (OTB, here after). My super cool test lead, Gopinath, suggested that I should give you guys a tour of this feature so you can start working on it as soon as Beta 2 hits the stands! So – here I am, doing just that.

 

What is OTB?

 

OTB is a rich GUI front end to the VS Debugger in design mode. It provides a graphical visualization (1) of the objects created at design time from within the IDE and the GUI to interact with these objects. It also provides a GUI to interact with the classes in the Class View (CV, here after) & Class Designer (CD, here after).

 

OTB was designed with the following in mind, which make it pretty interesting:

1.       Design time debugging (?!?): Users create and interact with objects at design time and *without* having to write driver code and/or starting a debugging session. These objects are instances of either the classes the users has just written or the classes from the referenced assemblies.

2.       It provides rich GUI: Users are guided by a rich wizard type GUI in all their tasks viz. instantiating class, calling methods, inspecting objects, and a lot of other activities.

3.       It is language agnostic: OTB respects the user’s individuality (J, in terms of choice of coding language) by performing its tasks, irrespective of whether it is a J#, C# or VB project – yup, OTB Beta 2 supports VB! (2)

 

Who/what is OTB meant for?

 

OTB is intended to simplify the debugging & testing the functionality of classes & their methods within a VS project or any of its references.

 

In other words, it could be used to shorten the design-code-debug loop for almost all classes & their methods you write. E.g. say you are writing a class library that provides utility classes/methods – you could use OTB to quickly test your code. The alternative is to create a console application as a driver for your code and then step through the driver application as it calls your code.

 

A corollary to the above is that OTB helps you to explore the functionality provided by the classes in a 3rd party or .NET FX assembly. E.g. say you were banging your head on the wall with a question like:

 

Umm… What was that function again? The one in System.Environment that returned all the process environment variables in the current process? What exactly does it return?

 

Well with OTB around, the good news is you don’t have to create a console application and write code to call System.Environment.GetEnvironmentVariables, store its return value in a System.Collections.IDictionary reference and then step through the driver application to examine the return value. Using OTB all you have to do is create the bare bones zero impact J# console application, navigate to System.Environment in the CV and invoke the System.Environment.GetEnvironmentVariables method using a GUI and save the return value on the test bench. Once the return value is in the test bench, you can simply use the Enhanced Debugger Datatips to do pretty much anything you want with it.

 

While on the subject of survey and exploration, I have to confess that I have myself used the OTB at times to quickly verify whether some of OTB’s internal classes were indeed working the way I wanted them to.

 

Another thing to note is that OTB with its rich GUI and its language agnostic behavior along with the CD will probably attract the new timers (3), who are comfortable with GUIs and all but not so comfortable with debugging yet. They are trying to build a strong foundation in Computer Science by first learning the basics of OOP amongst other concepts. They should not have to delve deep into language syntax/semantics and other language idiosyncrasies. I mean, from within a class, why would a beginner care how to call the instance methods? He doesn’t need to know that you have to do a this.GetType() in J# or me.GetType() in VB, well not just yet, at least!

 

Hmm… OK, enough ranting for a day! Let’s proceed! J

 

Who/what is OTB *not* meant for?

 

OTB is designed/developed to provide a tool for the academia to help teachers/students for teaching/learning various concepts of software engineering. A hobbyist developer can also use it to explore the various 3rd party class libraries written for .NET FX. Although, theoretically anyone can use it during development and testing of complex software projects, OTB, depending on the code will probably not scale up adequately for large projects!

 

Specifically OTB is an unlikely tool:

1.       For folks involved in large/complex or distributed projects.

2.       For doing unit testing on a given piece of code.

3.       For extending/automating via DTE and other automation interfaces.

4.       For Just-in-Time or post mortem debugging.

5.       To be used in the break/run modes of the Visual Studio 2005 IDE.

 

Where/how/when is OTB available?

 

Here is a conversation we might just have at this point of time:

 

Me: You have done well, going through this huge pile of blog. And now I sense that you wish to continue your search for young OTB.

You: Yes, my master!

Me: Patience, my friend, in time he will seek you out and when he does, you must bring him before me. He has grown strong. Only together can we turn him to the unplugged side of debugging.

You: As you wish, my master!

Me: Everything is proceeding as I have foreseen.

Me: <laugh type="evil">eh eh eh he he</laugh>

 

Well the good news is that you can play with this Visual Studio 2005 Beta 2. As always, if you need more information you can contact me and I will put you through to someone who can answers your questions.

 

And finally…

 

In my next set of blogs, I will walk you through the OTB functionality. Basically what you can do and how! I will also present a few use cases that illustrate how OTB can be used. These won’t be the canonical cat.Meow()/dog.Bark() type examples, but something more realistic.

 

Finally the ever so clichéd: Hope you enjoy working with OTB as much as we have enjoyed designing/developing/testing it for you!

 

Please note that my blogs aren’t the official documentation on OTB or any other feature or component that write about – if you do see any discrepancy between my blogs and the product – then it is me goofing up big time! You are most welcome to contact me to get things clarified. Please also refer to the disclaimer on the left.

 

Here is the official OTB documentation on MSDN. This is based on the Beta 1 bits. So you will have to wait a while for the Beta 2 docs to appear at this link.

 

(To be continued…)

 

Notes:

1.      (1) Not to be confused with Debugger Visualizers.

2.      (2) Party time for Elvis and Mort! Einstein will probably have to wait for v2! Sorry about that! :)

3.      (3) I was a new-timer w.r.t. computer programming in my 10th grade… Nowadays, the new timers are from what? The 2nd grade? 3rd? 4th? Ummm… I don’t know…

 

Posted by parthopdas | 9 Comments
Filed under:

Some of the coolest articles on Visual J#...

Hello everyone...

The entire division has been really really busy over the last few weeks! We have just about begun the final phase of the Visual Studio 2005 Beta 2 release. And personally I haven’t much time for anything else – totally absolutely heads down on bug fixing!

Well, what better job in the world that to write code, debug and fix bugs? And what better place in the world to work than in Microsoft Corporation?

Visual J# rocks!!! Visual Studio rocks!!! Microsoft Corporation rocks!!!

Anyways coming back the topic of this blog, I wanted to let everyone know about some of the coolest articles on Visual J#.  Here they are…

Visual J# language features:

1.       Delegates in J#: Understand what delegates are and how to use them from Visual J#.

2.       Exception handling in J#: How does Visual J# integrate the Java-language exception handling model with the one provided by the CLR.

3.       Properties in J#: Learn how to author and consume .NET properties and indexers from Visual J#.

 

Migrating to .NET:

1.       Moving from WFC to the .NET Framework: An overview and comparison of Windows Foundation Classes and .NET Framework class library.

2.       Migrating Java Applets to Microsoft J# Browser Controls: Learn all about J# Browser Controls and how to migrate Java Applets to .NET Framework… (There are 4 sub-articles, be sure to go through them also)

 

Problem solving using Visual J#:

1.       Design Concepts using Visual J#: Review design solutions available in Visual J#.

2.       Delegates in Action: Learn how to use Delegates in Visual J# for problem solving

3.       Solving Constraints: This is a cool one – design a system representing an equation with more that one variable.

 

These articles are written by Pratap Lakshman. He is the Lead Program Manager in the Visual J# team. And he is a totally cool dude! You can reach him here.

 

For more articles stay tuned on this or if you have an RSS reader, subscribe to the RSS feed for Visual J#.

 

In my next post, I will be writing on Object Test Bench – my pet feature in Visual Studio 2005 and the one I have been working on for the last year or so…

 

See you later…

Posted by parthopdas | 0 Comments
Filed under:

Visual J#: What is it?

Sometime back the following question came up on an internal discussion:

 

"How to call method written in x lanuage from C#.  In particular, I have several Java-language classes that I don't want to rewrite them in C#.  How can I call them from C#.  I understand that I can call a C/C++ dll from C# and load jvm within the c/c++ code.  But is there anything more efficient?"

 

The answer to this question pretty much explains why Visual J# exists. Here is what I replied to the above question:

 

Apart from the load-jvm-and-execute option, you do have a few sleeker options:

 

1.       If you have compiled .class binaries only and you don’t have access to the Java-language sources, you can use JBImp.exe (part of .NET SDK) to convert the .class files to managed assemblies.

JBImp will convert all compiled code that meets certain conditions.

Once you have managed assemblies – you can pretty much use it from any managed language – J#, C#, VB, MC++, etc. 

 

2.   If you have access to the J++ project and associated Java-language sources and you want to continue coding in the same language, you should run your sources through the J++ to J# Upgrade Wizard (part the VS IDE). This upgrade wizard will generate an upgrade report that lists all compatibility issues etc. and gives you suggestions/workarounds on how to modify them so that they can be compiled for the .NET platform.

Once the upgrade wizard is done you will get J# code that can be compiled (with the modifications suggested in the upgrade report) into managed assemblies using the J# complier.

(Note that if you do not have access to only the Java-language sources and not the J++ project, you may not be able to run J# Upgrade Wizard. Nevertheless you can simply compile the sources and as long as these conditions are met)

 

3.   If you are keen on moving into .NET completely, C# should be your choice of language.

In that case you will need to run your sources through the Java Language Conversion Assistant (part of VS IDE).

The JLCA will basically convert your Java-language sources to C# sources and C# compiler will do the rest for you.

(Please see the foot note on JLCA)

 

Having said that, J# is the solution for Java-language developers on .NET platform.

The Visual J# tool comes with its compiler, a Java binary importer (JBImp above) and complete java-language support subject to this. Visual J# is also integrated into the VS IDE – you create/manage projects (and migrate J++ projects), use a number RAD tools for a super coding experience, use a rich visual debugger, build deployment solutions, etc.

 

For more information please visit the Visual J# home page. There you can get the latest information, articles, documentation, downloads, etc.

 

In my next post I will talk about Visual J# 2005 features and which of those I work on.

 

Please note:

1.       JLCA is a very powerful tool and is shipped by a sister team of Visual J#, internally called the NetStep Team. TBright is a Program Manager in that team.

2.       Microsoft Visual J# .NET is not a tool for developing applications intended to run on a Java virtual machine. Applications and services built with Visual J# .NET will run only in the .NET Framework; they will not run on any Java virtual machine. Visual J# .NET has been independently developed by Microsoft. It is neither endorsed nor approved by Sun Microsystems, Inc.

 

Posted by parthopdas | 5 Comments
Filed under:
More Posts Next page »
 
Page view tracker