Sunday, September 02, 2007

Reflection on Generic, Part 3 - Instantiate Generic Type

In this post, we will look at how to use reflection to instantiate a generic type.
First, let start with an example of how to do it in the usual way without reflection.

static void Main(string[] args)
{
List<string> list = InstatiateList();
list.ForEach(delegate(string s) { Console.WriteLine(s); });
Console.ReadLine();
}

private static List<string> InstatiateList()
{
List<string> listOfString = new List<string>();
listOfString.Add("AAA");
listOfString.Add("BBB");
return listOfString;
}
The above code will print out
AAA
BBB

Now, lets do it the reflection way.
static void Main(string[] args)    
{
List<string> list = InstatiateListReflectionWay();
list.ForEach(delegate(string s) { Console.WriteLine(s); });
Console.ReadLine();
}
 
private static List<string> InstatiateListReflectionWay()
{
// Get the metadata for List_Of_T
Type t = typeof(List<>);
 
// Make a type definition for List_Of_String
Type[] typeArg = new Type[1] { typeof(string) };
Type listOfStringDef = t.MakeGenericType(typeArg);
 
// Get the method metadata for Add() method.
MethodInfo mi = listOfStringDef.GetMethod("Add");
 
// Create an instance of List_Of_String.
object listOfString = Activator.CreateInstance(listOfStringDef);
 
// Add two element to the list.
mi.Invoke(listOfString, new object[] { "CCC" });
mi.Invoke(listOfString, new object[] { "DDD" });
return (List<string>)listOfString;
}

The above code will print out:
CCC
DDD

Even when you use reflection, the runtime still give you strongly type checking protection against your code. To prove this, insert the following code before the return statement in InstatiateListReflectionWay().
mi.Invoke(listOfString, new object[] { 123 });

This time, when you run the code again, you will see an exception thrown.
Exception thrown.
Exception thrown when insert a number into list_of_string. Click to view in full size.

Labels: , ,

Reflection on Generic, Part 2 - Reflecting Type Parameter

In the previous post, you have know how to retrieve type metadata for a generic type. In this post, let's walk through how to retrieve metadata for the type parameter. Let's use the following code as example:
public interface IPrint
{
string Print();
}
 
public class PrintingDevice<T> where T: class, IPrint, new()
{
public T Device;
}
 
public class ValueGenericType<T> where T : struct
{
public T Value;
}
 
....
 
private static void DumpType(Type t)
{
Console.WriteLine("Is Generic Type : {0}", t.IsGenericType);
Console.WriteLine("Type Name : {0}", t.FullName);
 
Type[] genericArguments = t.GetGenericArguments();
 
Console.WriteLine("Number of type parameter : {0}", genericArguments.Length);
foreach (Type typeArg in genericArguments)
{
// Check whether the current type represent a Generic Parameter.
Console.WriteLine("Is Generic Parameter : {0}", typeArg.IsGenericParameter);
 
// Get the constraint specified for type parameter
GenericParameterAttributes attr = typeArg.GenericParameterAttributes;

if ((attr & GenericParameterAttributes.DefaultConstructorConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Default constructor constraint specified.");
}
 
if ((attr & GenericParameterAttributes.ReferenceTypeConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Reference type constraint specified.");
}
 
if ((attr & GenericParameterAttributes.NotNullableValueTypeConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Value type constraint specified.");
}
 
Type[] typeConstraints = typeArg.GetGenericParameterConstraints();
if (typeConstraints.Length > 0)
{
foreach (Type typeConstraint in typeConstraints)
{
Console.WriteLine("Type Constraint : {0}", typeConstraint.FullName);
}
}
else
{
Console.WriteLine("No type constraint specified.");
}
}
}


Run the following code with PrintingDevice,
Type t = typeof(PrintingDevice<>);
DumpType(t);

and the outcome will be :
Is Generic Type : True
Type Name : GenericConstraint.PrintingDevice`1
Number of type parameter : 1
Is Generic Parameter : True
Default constructor constraint specified.
Reference type constraint specified.
Type Constraint : GenericConstraint.IPrint


Run the code again with ValueGenericType,
Type t = typeof(ValueGenericType<>);
DumpType(t);

and the outcome will be :
Is Generic Type : True
Type Name : GenericConstraint.ValueGenericType`1
Number of type parameter : 1
Is Generic Parameter : True
Default constructor constraint specified.
Value type constraint specified.
Type Constraint : System.ValueType


Type.GetGenericArguments() will return an array of type parameters specified for the generic type.

Type.IsGenericParameter will return true if the current type represent a type parameter. If the type represent a type parameter, then the type will have no name.

Type.GenericParameterAttributes will return the constraints specified for that type parameter.

Type.GetGenericParameterConstraints() will return an array of type that are specified as the constraint for the type parameter.

Labels: , ,

Reflection on Generic, Part 1

You can use reflection against generic type to get metadata information about a generic type as well as instantiate a generic type with type argument. In this post, I will walk you through how to retrieve metadata about a generic type.

To check whether a type is a generic type, you use the Type.IsGenericType property.
Let start with a simple example:
Type s = typeof(string);
// This will print False.
Console.WriteLine(s.IsGenericType);
// This will print System.String
Console.WriteLine(s.FullName);

Since System.String is not a generic type, it will print False. Now let's use an example with generic type:
Type t = typeof(List<>);
// This will print True.
Console.WriteLine(t.IsGenericType);
// This will print System.Collections.Generic.List`1.
Console.WriteLine(t.FullName);
 
Type d = typeof(Dictionary<,>);
// This will print True.
Console.WriteLine(d.IsGenericType);
// This will print System.Collections.Generic.Dictionary`2.
Console.WriteLine(d.FullName);

In the above example, both will print True. Note that to retrieve type metadata for a generic type, you need to use the <> after the generic type name to denote the number of type parameters specified for that generic type. The number of type parameters are part of the type signature. It is perfectly legal to declare the following:

class C1<Y> { ... }
class C1<Y,T> { ... }

Going back to the example, since List only has one type paratemer, I just specify <> to indicate I want to the List generic class with one type parameter. For Dictionary class take take two type parameter, I specify <,> to indicate I want the Dictionary generic class with two type parameter.

When print out the full name of the class, notice that there is a number at the end of the class name. The number is called Arity which indicate the number of type parameter that the generic type have.

Labels: , ,

Saturday, September 01, 2007

Commodity and Differentiation feature

Mainly, we can divide product features set into 2 category: Commodity and Differentiation. Commodity is the set of core features that every product that play in that market space must have. For example, if you are developing a word processor, content formatting capability is a must; If you are developing a CRM product, ability to track contact and opportunity is a must. Customer always expects the feature will be there in the product. It is not compelling to have them, but surprise of not to have them.

Differentiation, as its spelled, is product feature that differentiate one product from another. Differentiation feature is what that give a product market advantage or to serve a niche in the market space. It is the type of feature that:
a) Nice to have but not essential to product of that class.
b) Allow the product company to charge more for their product.
c) If implemented correctly and used to maximum advantage, it can redefine the game, become a commodity and possibly turn the company to become the market leader.

For example, in a word processing product, it is nice but not essential to have a full drawing and diagramming capability. User who write article or book need to have both content formatting capability and graphics drawing capability within the same product because they need to have illustration for their content. Usually, they don't mind to pay a little more to get the extra feature that they want. But for majority of user, they might not need this capability to be included.

Commodity feature can also be implemented in different product in different ways to include different functions and capabilities which in turn can become a differentiation fact. For example, in automobile industry, airbag is a commodity feature because it is an essential safety feature. You can't sell a car if you don't have airbag. However, while most cars have only one airbag at the driver seat, having the second airbag at front passenger seat is a compelling safety feature (This is just a hypothetical example. This is true many years ago, but today most car have two airbag as standard).

Labels:

Product Planning : Vision first, not Feature first.

I believe that for a product to be successful, it is very important to get the product planning right. Product planning is the first activity when product team starts to think what to build for vNext or vNext+1 release.

Some people start this activity by listing down a list of features that they think they want to include for the next release. While feature list is important, I don't think that is the right way to start. Customer does not buy software product just because it has cool feature, but because the product itself has a compelling story that make them to be more productive.

Given the feature list, now the question is what features we should deliver for the next release to make it more compelling? Some people will look at their resource and time availability and pick a set of feature that can be delivered with that time frame. The problem with this approach is that your product may end up with a set of dis-integrated features and perceived as half baked.

So what you can do about it? Remember in the first paragraph: the product itself need to have a compelling story to tell for it to be attractive. You marketing guy need to be able to articulate a smooth flowing story to their customer where they can show how various features and functions can be used in a coherent way. To achieve this, you need to have a product vision.

Product vision describe what you want the product to be able to do for your customer and how far you want to take the product to. From the product vision, you derive a set of core values that deliver to that vision. Then you look at what features and functions are important in order to materialize the core values.

Product vision is important for the following aspects:

a) It allows you to articulate a simple message to your customer. Customer can clearly see what you are doing and be less confused.

b) Your customer can easily see whether what you deliver is align to what they want. Successful company treats their customer as their partner. They share vision, roadmap and progress with their customer so that they can engage in a stronger long term relationship and move forward together. As a customer, you don't just to pay money to get some products. You want to ensure your vendor is able to help you to be successful.

c) Product vision allows you to clearly identify the strength and short coming of your product. If give you a roadmap of what you should do next to improve the product in the future.

d) Product vision establishes a single view point for all people in the team. Whatever role your team member is in the product group, all of them are able to articulate the same message when asked. And more importantly, no people will be lost at direction.

e) It give you a focus point for not to be diverted by distraction. If there is a sudden market change, you can easily see whether the changes will actually affect you and what you can do to re-align your goal with the market.

f) It give you a base to prioritize you feature. Features and functions that do not fit to materialize the vision should be at low priority.

g) If your developers are faced with conflict and hard design decision, they can make the decision based on which materialize the vision better.

It is important that the product vision is spread as wide as possible so that everyone can march in the same direction. Product vision that is not shared by everybody in the team is as good as none. How can you be motivated and convinced if you don't know where you are going and what you are contributing to.

But what if you are a solution or consulting house? What if you are not building product, rather you build custom software or implement third party software product as solution to your customer? How does this apply to you?

In such cases, it is important you first understand their business problem, the environment they are operating under, what is their IT direction and what they hope to achieve from the solution. Then you derive a solution map that correspond to their business and IT goal. Your solution map consists of a set of milestones each with specific goal and deliverables and you deliver based on that promise. This approach can form a healthy strong and long term relationship with your customer because both have a common understanding and expectation as early as the project start. In case their business environment and competitive surface change, it allows you and your customer to easily re-prioritize each other goal and evolve the relationship without hurting each other benefits.

Business agility is the ability to adapt to changing business environment and accept the fact that change is part of the game. However, you can only change and understand the change impact if you have some sort of ground work to based upon for assessment. After all, how can you change course if you don't even know where you are heading. Product vision gives you this ground work.

Labels: