Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Dynamic Support in .NET 4<br />Basharat Hussain<br />
List the core areas of C# 4.0<br />Developer should focus on:<br />using the dynamic keyword as a data type that supports ...
Major Theme<br />“ C# 4.0 primarily focus on dynamic programming. "<br />
Dynamic Dispatch<br />C#4 now supports dynamic late-binding.<br />Helps communicate with systems not based on .NET Platfor...
Approach 1 – Using Proxy<br />import the foreign model directly into .NET as a proxy – like COM Interop<br />COM Interop -...
Approach 2 – use Dynamic<br />Forget about type safety at compile time<br />We already doing things at runtime in C# 3.5 a...
Reflection vs. dynamic<br />Reflection <br />object o = GetObject();<br />Type t = o.GetType();<br />objectresult = t.Invo...
Dynamic Keyword<br />The dynamic  keyword in C# 4.0<br />Tell compiler – variable type is unknown until runtime<br />dynam...
Dynamic Usability<br />Need to cast between decimal and double <br />decimal foo = GetDecimalValue(); <br />foo = foo / 2....
Static vs. Dynamic Switching<br />Customer c = new Customer(); <br />dynamic  d = c; // static to dynamic, easy enough<br ...
RuntimeBinderException<br />try<br />{<br />dynamic d = "this is a string";<br />d.Foo();<br />}<br />catch (Microsoft.CSh...
Assignment<br />Any object can be implicitly converted to dynamic<br />Conversely, there is an “assignment conversion” fro...
The following example throws a RuntimeBinderException because an int is not implicitly convertible to a short:<br />   <br...
Dynamic binding<br />The result of any dynamic operation is itself of type dynamic<br />The process of selecting which ope...
Possibilities<br />dynamicGetDynamicObject()<br />{<br />returnnewobject();<br />}<br />void Demo()<br />{<br />var d = Ge...
Dynamic reusability<br />Possible but not recommended<br />Dynamic can reuse a variable for different types of data<br />d...
Dynamic dispatch - by Example<br />dynamic list = GetDynamicList();<br />dynamicindex1 = GetIndex1();<br />dynamicindex2 =...
Dynamic Vs. Object (similarities)<br />Type inference algorithms as described in §7.4 will prefer dynamic over object if b...
Dynamic vs. Object (similarities)<br />Type dynamic does not have a separate runtime representation from object<br />typeo...
Dynamic vs. object (similarities) <br />This statement is correct<br />List<dynamic> dList = new List<object>();<br />You ...
Dynamic vs. object (differences) -Boxing Unboxing 	<br />Object o = 123;             // OK, Implicit cast from Int32 to Ob...
Dynamic vs. object (differences) - dynamic parameter != object –treat dynamic like actual types<br />classMyType<br />{<br...
The result of any dynamic operation is itself of type dynamic, with two exceptions:<br />The type of a dynamic constructor...
Implicitly Typed Local Variables and Arrays<br />Keyword var - type is inferred by the compiler from the expression on the...
Var - Usage<br />varivar = 6 // compiled as an int<br />varsvar="Mony"; // compiled as a string<br />variarr_var=new[] {0,...
VarRestrictions<br />Is always local to a method and first time initialization<br />Cannot be null<br />Cannot be used as ...
DLR Architecture<br />The DLR Runs on Top of the CLR<br />
DLR Services<br />DLR adds three services to the CLR for better supporting dynamic languages<br />Expression Trees<br />Th...
Expression trees<br /><ul><li>The same expression trees used in LINQ, now improved for DLR to support statements ( languag...
Call site caching<br />A dynamic call site is a place in the code where you perform an operation like a + b or a.b on dyna...
Dynamic dispatch<br />Wikipedia says:<br />“Dynamic dispatch (dynamic binding) is the process of mapping a message to a sp...
Dynamic dispatch – underneth binders<br />Underneath the DLR there are binders that talk to a variety of different technol...
Dynamic dispatch mechanism<br />Runtime resolution is based on nature of dynamic variable<br />Cache Info: <br />Use call ...
Dynamic dispatch - by Example<br />dynamic d1 = new Foo();dynamic d2 = new Bar();string s;<br />d1.M(s, d2, 3, null);<br /...
COM automation interop – dynamic<br />Code in C#3<br />Type myType = Type.GetTypeFromProgID("IMyLib.MyClass"); <br />objec...
Limitations of Dynamic Lookup<br />Extension methods - not supported<br />Dynamic lookup will not be able to find extensio...
Limitation Example<br />dynamic collection = …;<br />var result = collection.Select(e => e + 5);<br />Select method is an ...
The Visitor Pattern and dynamic in C# 4<br />http://code.logos.com/blog/2010/03/the_visitor_pattern_and_dynamic_in_c_4.htm...
IDynamicMetaObjectProvider<br />
IDynamicMetaObjectProvider<br />Tells the DLR, "I know how to dispatch operations on myself.“<br />This interface contains...
Framework implementations<br />The .NET Framework already provides two implementations of IDynamicMetaObjectProvider:<br /...
ExpandoObject<br /> Expandosare expandable objects which means you can add properties, methods and even events at runtime....
Example – Expando Object<br />using System;<br />usingSystem.Dynamic;<br />namespaceDLRExample<br />{<br />classProgram<br...
ExpandoObject – CONT…<br />Can add methods at runtime - using lambda expressions. <br />Example: add method ChangeVehicleC...
ExpandoObject – CONT…<br />expando object also implements the generic IDictionaryinterface<br />So you can enumerate the m...
DynamicObject<br />Provides a base class for specifying dynamic behavior at run time. This class must be inherited from; <...
My Dynamic Object Implementation<br />Caller Code<br />dynamic d = newMyDynamicObject(); <br />d.Bar("Baz", 3, d);<br />So...
Usage<br />The Expando object is interoperable between different framework languages. So it is an obvious choice in situat...
BLOGS	<br />http://blogs.msdn.com/b/samng/archive/tags/dynamic/<br />http://blogs.msdn.com/b/cburrows/archive/tags/dynamic...
The Phantom Method<br />Rule of thumb:<br />Everything is convertible to dynamic – Implicit Conversion<br />Dynamic is not...
phantom method<br />publicclassC<br />{<br />publicvoid Foo(int x) { }<br />staticvoid Main()<br />    {<br />dynamic d = ...
phantom method<br />In each of these special situations compiler generates all the surrounding DLR code that prompts a run...
Overload resolution – phantom method<br />Since dynamic (d) is not convertible to anything (int), however, since we've got...
phantom method<br />If compiler detects C.Foo(d) taking dynamic as parameter<br />It genertaes two overloads: <br />Foo(in...
phantom method<br />The phantom will be introduced if:<br />All of the non-dynamic arguments are convertible to their resp...
phantom method<br />publicclassC<br />{<br />publicvoid Foo(int x, dynamic y) { ... }<br />staticvoid Main()<br />    {<br...
Advanced Dynamic Limitations <br />
Mutating values Types using dynamic<br />dynamicd = 10;<br />d++;<br />Console.WriteLine(d); //d=11<br />If right side is ...
Nested structmutation<br />Extending last issue on value type, if any of the dotted expressions were to bind to a value ty...
Nested structmutation - Example<br />publicstructS<br />{<br />publicint i;<br />} <br />publicclassD<br />{<br />publicSs...
Base calls<br />There is a restriction in the CLR that prevents the compiler from generating non-virtual calls on virtual ...
Explicitly implemented interface methods not supported<br />Interfaces are really compile time constructs, and have no run...
No phantom for private<br />The down side of this scenario is that you could make a call with a static receiver to a priva...
More interesting scenarios<br />
Static or dynamic?<br />publicclassC<br />{<br />staticvoid Main()<br />    {<br />Cc = newC();<br />dynamic d = 10;<br />...
Compiler ignores type inference of parameter type (and constraints)<br />Compiler assumes it is convertible at compile tim...
A complex scenario<br />publicinterfaceIAnimal { }<br />publicinterfaceIWatcher<in T> { }       //Contravariant in T<br />...
Analysis of Example<br />In the first call, this is all fine and good - runtime type inference would also fail on the call...
Language Interoperability<br />Calling from/to .NET  the dynamic objects written in <br />IronPython<br />IronRuby<br />
IronPython Installation<br />http://ironpython.net/<br />http://ironpython.codeplex.com/releases/view/54498<br />Iron Pyth...
Invoke IronPython from C#<br />Instantiating the IronPython object from C#4 - using dynamic<br />Steps:<br />Ensure IronPy...
Invoke IronPythonfrom C#<br />var runtime = Python.CreateRuntime();<br />var scope = runtime.ExecuteFile(@"....scriptshell...
Invoke C# “Dynamic Object” from C#/IronPython<br />publicclassMyDynamicObject : DynamicObject<br />    {<br />publicvoid F...
Invoke C# “Dynamic Object” from C#/IronPython<br />publicstaticvoid Execute()<br />{<br />    dynamic myDynamicObject = ne...
IronRuby Installation<br />http://www.ironruby.net/<br />http://ironruby.codeplex.com/releases/view/25901<br />Iron Ruby V...
Problem with Framework Designers<br />Dynamic <br />Lacks documentation<br />Lack compile-time type checking<br />Lack Per...
Lacks documentation<br />Severe lack of documentation. The entire application's architecture exists in the mind of the per...
Lack compile-time type checking<br />>>Dynamic Version<br />publicdynamic Foo(dynamic other)<br />{<br />dynamic clone = o...
Don’t Use Blindly<br />Answer: <br />Use dynamic-only-when-necessary and var-at-all-other-times<br />Purpose of dynamic in...
Very Bad Performance<br />If dynamicusage can be avoided, it should be avoided.<br />Statistical performance study<br />dy...
Generated Code – for interested ones<br />dynamic c = 10; int b = c * c; <br />
HTML DOM<br />If you write Silverlight applications, you might have the need today or in the future to access the HTML DOM...
HTML DOMExpects Dynamic Dispatch from JScript<br />JScript:<br />var loc = new VELatLong(latitude, longitude);<br />var pi...
Runtime semantics/sequence of dynamic binding<br /><ul><li>If the receiver is a dynamic object – i.e., implements IDynamic...
Otherwise the operation gets resolved at runtime in the same way as it would have at compile time, using the runtime type ...
If a constituent value derives from a literal, the dynamic binding is able to take that into account. For instance, some c...
If a constituent value of static type dynamic has the runtime value null, it will be treated as if the literal null was used.
Extension method invocations will not be considered – the set of available extension methods at the site of the call is no...
Upcoming SlideShare
Loading in …5
×

2.dynamic

2,085 views

Published on

C# 4.0 is now dynamic language. DLR feature is remarkable. See how you can get benefit from dynamicity.

Published in: Education, Technology
  • Be the first to comment

2.dynamic

  1. 1. Dynamic Support in .NET 4<br />Basharat Hussain<br />
  2. 2. List the core areas of C# 4.0<br />Developer should focus on:<br />using the dynamic keyword as a data type that supports runtime lookup<br />using optional parameters for constructors and methods<br />explicitly naming an argument being passing to a method<br />making generic interfaces and delegates covariant/contravariant<br />skipping the passing of optional parameters when making calls to COM objects<br />omitting the ref keyword when calling a method on a COM object<br />dynamically importing COM APIs and deploying without Primary InteropAssemblies (PIA)<br />working with the enhanced COM Interop features in C# 4.0<br />using the built-in .NET interfaces like IDynamicMetadataObject in .NET 4.0 – to interact with IronRuby/IronPython<br />
  3. 3. Major Theme<br />“ C# 4.0 primarily focus on dynamic programming. "<br />
  4. 4. Dynamic Dispatch<br />C#4 now supports dynamic late-binding.<br />Helps communicate with systems not based on .NET Platform<br />2 Approaches to communicate Non .NET systems<br />
  5. 5. Approach 1 – Using Proxy<br />import the foreign model directly into .NET as a proxy – like COM Interop<br />COM Interop - using TLBIMP tool (from C#1)<br />LINQ-to-SQL, contains a tool called SQLMETAL, which imports an existing database into C# proxy classes for use with queries (from C#3)<br />A tool that imports Windows Management Instrumentation (WMI) classes to C#<br />LINQ-to-SQL<br />WCF<br />
  6. 6. Approach 2 – use Dynamic<br />Forget about type safety at compile time<br />We already doing things at runtime in C# 3.5 and later<br />invokes a method on a JScriptobject<br />embed a SQL query in your ADO.NET application<br />Reflection <br />defer binding to run time<br />Interopin that case is with .NET itself<br />
  7. 7. Reflection vs. dynamic<br />Reflection <br />object o = GetObject();<br />Type t = o.GetType();<br />objectresult = t.InvokeMember("MyMethod", <br />BindingFlags.InvokeMethod, null, <br />o, newobject[] { });<br />inti = Convert.ToInt32(result);<br />Dynamic <br />dynamic o = GetObject();<br />inti = o.MyMethod();<br />
  8. 8. Dynamic Keyword<br />The dynamic  keyword in C# 4.0<br />Tell compiler – variable type is unknown until runtime<br />dynamic can be thought of as a special version of the type object that is “suspending belief” <br />dynamic is a static type that bypasses static type checking<br />dynamic d = GetCustomer(); <br />d.FirstName = "foo"; // works as expected<br />d.Process(); // works as expected<br />d.MissingMethod(); // No method found!<br />Dynamic declaration means<br />Runtime sets FirstName property<br />Runtime will call Process() method<br />Compiler is even happy and runtime notice that MissingMethod() is not defined in Customer class <br />Result is exception: RuntimeBinderException <br />
  9. 9. Dynamic Usability<br />Need to cast between decimal and double <br />decimal foo = GetDecimalValue(); <br />foo = foo / 2.5 ; // Code break because 2.5 typed as double<br />foo = Math.Sqrt(foo); // Code break because sqrt expects double<br />string bar = foo.ToString("c");<br />Dynamic magic in c#4 – No need to cast<br />dynamic foo = GetDecimalValue(); // still returns a decimal<br />foo = foo / 2.5; // The runtime takes care of this for us<br />foo = Math.Sqrt(foo); // Again, the DLR works its magic<br />string bar = foo.ToString("c");<br />
  10. 10. Static vs. Dynamic Switching<br />Customer c = new Customer(); <br />dynamic d = c; // static to dynamic, easy enough<br />d.FirstName= "foo"; <br />Customer newCust = d; // Works because d is a Customer<br />Person p = d; // works because Customer inherits from Person<br />SalesRep s = d; // throws RuntimeBinderException exception<br />Note: In the example above, no matter how many different ways we reference it, we only have one Customer object (c).<br />
  11. 11. RuntimeBinderException<br />try<br />{<br />dynamic d = "this is a string";<br />d.Foo();<br />}<br />catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException e)<br />{<br />Console.WriteLine(e.Message);<br />}<br />Output:<br />'string' does not contain a definition for 'Foo'<br />
  12. 12. Assignment<br />Any object can be implicitly converted to dynamic<br />Conversely, there is an “assignment conversion” from dynamic to any other type, provided normal implicit conversion in assignment is allowed – again at runtime<br />dynamic d= GetCustomer(); <br />string first = d.FirstName; // assignmentconversion<br />dynamic id = d.CustomerId; // no conversion<br />object last = d.LastName; // assignmentconversion<br />dynamic d = 10; //Rule: Dynamic is like object so boxing must happen for value types (explained next slides)<br />
  13. 13. The following example throws a RuntimeBinderException because an int is not implicitly convertible to a short:<br />   <br />  int i = 7;<br />     dynamic d = i;<br />     short j = d;                // throws RuntimeBinderException<br />
  14. 14. Dynamic binding<br />The result of any dynamic operation is itself of type dynamic<br />The process of selecting which operation to apply based on the types of constituent expressions is referred to as binding.<br />Binding Operations<br />Member access: d.M<br />Method invocation: d.M(d1,…,dn)<br />Delegate invocaton: d(d1,…,dn)<br />Element access: d[d1,…,dn]<br />Constructor calls: new C(d1,…,dn)<br />Overloaded unary operators: +, -, !, ~, ++, --, true, false<br />Overloaded binary operators: +, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==,!=, >, <, >=, <=<br />Compound assignment operators: +=, -=, etc.<br />Implicit and explicit conversions<br />
  15. 15. Possibilities<br />dynamicGetDynamicObject()<br />{<br />returnnewobject();<br />}<br />void Demo()<br />{<br />var d = GetDynamicObject(); // getting as return type <br />d.M(7); // calling methods<br />d.f = d.P; // getting/settings fields and properties<br /> d[“one”] = d[“two”]; // getting/setting through indexers<br />int i = d + 3; // calling operators<br />string s = d(5,7); // invoking as a delegate<br />}<br />
  16. 16. Dynamic reusability<br />Possible but not recommended<br />Dynamic can reuse a variable for different types of data<br />dynamic foo = 1234567890;<br />System.Console.WriteLine(foo);<br />foo = "John Charles";<br />System.Console.WriteLine(foo);<br />foo = true;<br />System.Console.WriteLine(foo);<br />
  17. 17. Dynamic dispatch - by Example<br />dynamic list = GetDynamicList();<br />dynamicindex1 = GetIndex1();<br />dynamicindex2 = GetIndex2();<br />strings = list[++index1, index2 + 10].Foo();<br />Fivedynamic operations in one line <br />First, there’s the dynamic pre-increment on index1, <br />then the dynamic add with index2. <br />Then a dynamic indexer get is called on list. <br />The product of those operations calls the member Foo. <br />Finally, the total result of the expression is converted to a string and stored in s. That’s five dynamic operations in one line, each dispatched at run time.<br />
  18. 18. Dynamic Vs. Object (similarities)<br />Type inference algorithms as described in §7.4 will prefer dynamic over object if both are candidates<br />There is an implicit identity conversion between object and dynamic<br />There is an implicit identity conversion between constructed types that differ only by dynamic versus object<br />Method signatures that differ only by dynamic versus object are considered the same and can be overridden<br />Like with object, there is an implicitconversion from every type (other than pointer types) to dynamic and an explicit conversion from dynamic to every such type.<br />
  19. 19. Dynamic vs. Object (similarities)<br />Type dynamic does not have a separate runtime representation from object<br />typeof(dynamic) == typeof(object)is true<br />This principle extends to constructed types and array types<br />typeof(List<dynamic>) == typeof(List<object>)<br />typeof(dynamic[]) == typeof(object[])<br />
  20. 20. Dynamic vs. object (similarities) <br />This statement is correct<br />List<dynamic> dList = new List<object>();<br />You can override Equals method that take object parameter – with dynamic<br />class Employee<br />{ <br /> public override bool Equals(dynamic obj) { /* ... */ } <br />}<br /> Use dynamic as real type argument or, as a return value – even across assemblies<br />public dynamic GetDynamicThing()<br />
  21. 21. Dynamic vs. object (differences) -Boxing Unboxing <br />Object o = 123;             // OK, Implicit cast from Int32 to Object (boxing)<br />Int32 n1 = o;                // Error: No implicit cast from Object to Int32<br />Int32 n2 = (Int32) o;     // OK: Explicit cast from Object to Int32 (unboxing)<br />dynamic d = 123;          // OK: Implicit cast from Int32 to dynamic (boxing)<br />Int32 n3 = d;                //OK: Implicit cast from dynamic to Int32 (unboxing)<br />
  22. 22. Dynamic vs. object (differences) - dynamic parameter != object –treat dynamic like actual types<br />classMyType<br />{<br />publicvoid Method(int x, int y) { Console.WriteLine("Int function"); }<br />publicvoid Method(string s, string t) { Console.WriteLine("Str function"); }<br />publicvoid Method(object o, object p) { Console.WriteLine(“Obj function"); }<br />}<br />classProgram<br />{<br />staticvoid Main(string[] args)<br /> {<br />dynamic d = newMyType();<br />d.Method(10, 20); // Calls the int version.<br />d.Method("abc", "def"); // Calls the string version. <br />d.Method((object)10, (object)20); // Calls the object version.<br />d.Method((object)"abc", (object)"def"); // Calls the object version.<br />// *<br />d.Method((dynamic)10, (dynamic)20); // Calls the int version. (PHANTOM)<br />d.Method((dynamic)"abc", (dynamic)"def"); // Calls the string version.<br />(PHANTOM)<br />// Repeat of the last 4 cases.<br />d.Method(GetInt(), GetInt()); // Calls the object version.<br />d.Method(GetString(), GetString()); // Calls the object version.<br />d.Method(GetDynamicInt(), GetDynamicInt()); // Calls the int version.<br /> }<br /> staticobjectGetString()<br /> {<br />return ("abc");<br /> }<br />staticobjectGetInt()<br /> {<br />return (5);<br /> }<br />staticdynamicGetDynamicInt()<br /> {<br />return (5);<br /> }<br />}<br />
  23. 23. The result of any dynamic operation is itself of type dynamic, with two exceptions:<br />The type of a dynamic constructor call is the constructed type<br />The type of a dynamic implicit or explicit conversion is the target type of the conversion.<br />dynamicis very slow– so use only when necessary otherwise use var.<br />
  24. 24. Implicitly Typed Local Variables and Arrays<br />Keyword var - type is inferred by the compiler from the expression on the right side of the initialization statement.<br />Inference type support<br />Built-in type<br />Anonymous type (will be discussed later)<br />User-defined type<br />Type defined in the .NET Framework class library<br />
  25. 25. Var - Usage<br />varivar = 6 // compiled as an int<br />varsvar="Mony"; // compiled as a string<br />variarr_var=new[] {0,1,2 }; // compiled as int[] - array<br />varsarr_var=new[] {"hello",null,"world" }; // string[]a<br />// query is compiled as IEnumerable<br />varquery = from c in customerswhere c.Name =="Mony"select c;<br />// anonymous_variable is compiled as an anonymous type<br />varanonymous_variable =new { Name = “Sami", Job = "Web Developer" };<br />var list =new List();<br />
  26. 26. VarRestrictions<br />Is always local to a method and first time initialization<br />Cannot be null<br />Cannot be used as class’s field<br />Cannot be uses in initialization again with variable<br />var i = i++;  - compile-time error<br />Multiple implicitly-typed variables cannot be initialized in the same statement.<br />
  27. 27. DLR Architecture<br />The DLR Runs on Top of the CLR<br />
  28. 28. DLR Services<br />DLR adds three services to the CLR for better supporting dynamic languages<br />Expression Trees<br />The same expression trees used in LINQ, now improved to support statements ( language syntaxes and semantics).<br />Call Site Caching<br />For improved efficiency.<br />Dynamic Dispatch<br />Dispatches invocations to the appropriate binder.<br />Dynamic Object Interoperability <br />These are essentially a set of interfaces that help creation of dynamic objects.<br />
  29. 29. Expression trees<br /><ul><li>The same expression trees used in LINQ, now improved for DLR to support statements ( language syntaxes and semantics).</li></ul>DLR has extended LINQ expression trees to include control flow, assignment, and other language-modeling nodes<br />
  30. 30. Call site caching<br />A dynamic call site is a place in the code where you perform an operation like a + b or a.b on dynamic objects. DLR Cache usage/ characteristics of dynamic objects a and b. <br />If such operation performed previously, the DLR retrieves all the necessary information from the cache for fast dispatch<br />Also cache  information about operations on the ‘Dynamic Objects’<br />
  31. 31. Dynamic dispatch<br />Wikipedia says:<br />“Dynamic dispatch (dynamic binding) is the process of mapping a message to a specific sequence of code (method) at runtime. This is done to support the cases where the appropriate method cannot be determined at compile-time (i.e. statically)”.<br />Binders are used by DLR<br />
  32. 32. Dynamic dispatch – underneth binders<br />Underneath the DLR there are binders that talk to a variety of different technologies:<br />.NET Binder<br />Allows to talk to .NET objects.<br />JavaScript Binder<br />Allows to talk to JavaScript in SilverLight.<br />IronPython Binder<br />Allows to talk to IronPython.<br />IronRuby Binder<br />Allows to talk to IronRuby.<br />COM Binder<br />Allows to talk to COM.<br />Otherwise<br />Throw Exception: RuntimeBinderException<br />
  33. 33. Dynamic dispatch mechanism<br />Runtime resolution is based on nature of dynamic variable<br />Cache Info: <br />Use call site cahe information, if operation on object is previously performed<br />COM objects<br />COM Interopscenarios - Calling through IUnknown and IDispatch interfaces of COM<br />Office automation<br />Dynamic objects<br />Consuming types written in dynamic languages as IronPython and IronRuby to implement their own dynamic object models<br />HTML DOM to allow direct access to the object’s properties<br />implements the interface IDynamicObjectIDynamicMetaObjectProvider<br />Plain objects<br />Using reflection against an underlying CLR type<br />
  34. 34. Dynamic dispatch - by Example<br />dynamic d1 = new Foo();dynamic d2 = new Bar();string s;<br />d1.M(s, d2, 3, null);<br />“Perform an instance method call of M with the following arguments:<br />a string <br />a dynamic <br />a literal int 3<br />a literal object null”<br />Resolution Sequence At Runtime: <br />assume that the actual type Foo of d1 is not a COM type <br />And it does not implement IDynamicObjectIDynamicMetaObjectProvider<br />Then proceed following way<br />Use Reflection and get actual runtime types of the two objects, d1 and d2, >> Foo for d1 and Bar for d2.<br />Method lookup and overload resolution is performed for Foo.M(string,Bar,3,null)<br />If found – inoke it<br />Otherwise throw RuntimeBinderException<br />
  35. 35. COM automation interop – dynamic<br />Code in C#3<br />Type myType = Type.GetTypeFromProgID("IMyLib.MyClass"); <br />object obj = Activator.CreateInstance(myType); <br />object[] args = new object[2]; <br />args[0] = "Hello"; <br />args[1] = 3; <br />myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, args);<br />New Code in C#4<br />================<br />Type myType = Type.GetTypeFromProgID("IMyLib.MyClass"); <br />dynamic <br />{ <br />object obj = Activator.CreateInstance(myType); <br />obj.MyMethod("Hello", 3); <br />}<br />
  36. 36. Limitations of Dynamic Lookup<br />Extension methods - not supported<br />Dynamic lookup will not be able to find extension methods. Whether extension methods apply or not depends on the static context of the call.<br />Anonymous functions as parameters - not supported<br />Anonymous functions (i.e. lambda expressions) cannot appear as arguments to a dynamic method call. The compiler cannot bind (i.e. “understand”) an anonymous function without knowing what type it is converted to<br />
  37. 37. Limitation Example<br />dynamic collection = …;<br />var result = collection.Select(e => e + 5);<br />Select method is an extension method to collection, dynamic lookup will not find it.<br />object collection = context.Students.Select( s=><br /> new { Id = s.Id, Name = s.Name}).ToList();<br />dynamic d = collection;<br />int count = d.Count;<br />Because collection is anonymous type so dynamic cannot understand it.<br />
  38. 38. The Visitor Pattern and dynamic in C# 4<br />http://code.logos.com/blog/2010/03/the_visitor_pattern_and_dynamic_in_c_4.html<br />Dynamic can even avoid Visitor Pattern in some cases<br />publicclassMySpecialFunctions<br />{ <br />publicvoid Execute(int x) {...} <br />publicvoid Execute(string x) {...} <br />publicvoid Execute(long x) {...} <br />}<br />With Multi-dispatch case<br />dynamic x = getx(); <br />varmyFunc = newMySpecialFunctions(); <br />myFunc.Execute(x);<br />
  39. 39. IDynamicMetaObjectProvider<br />
  40. 40. IDynamicMetaObjectProvider<br />Tells the DLR, "I know how to dispatch operations on myself.“<br />This interface contains single method:<br />DynamicMetaObjectGetMetaObject (Expression parameter)<br />Blog Example<br />http://blogs.msdn.com/b/cburrows/archive/2008/10/28/c-dynamic-part-ii.aspx<br />
  41. 41. Framework implementations<br />The .NET Framework already provides two implementations of IDynamicMetaObjectProvider:<br />ExpandoObject: IDynamicMetaObjectProvider<br />DynamicObject: IDynamicMetaObjectProvider<br />
  42. 42. ExpandoObject<br /> Expandosare expandable objects which means you can add properties, methods and even events at runtime. You can also set and get the values of such members.<br />Can also pass Expando objects as parameters to other methods<br />Limitation: Will not get intellisense on the dynamic object because they are resolved at runtime<br />MSDN Example: http://msdn.microsoft.com/library/system.dynamic.expandoobject.aspx<br />
  43. 43. Example – Expando Object<br />using System;<br />usingSystem.Dynamic;<br />namespaceDLRExample<br />{<br />classProgram<br /> {<br />staticvoid Main(string[] args)<br /> {<br />dynamic Vehicle = newExpandoObject();<br />Vehicle.Make = "Cultus";<br />Vehicle.Model = "2008";<br />Vehicle.Engine = "4 cylinder";<br />Vehicle.Color = "Silver";<br />WriteVehicleDetails(Vehicle);<br />Console.ReadLine();<br /> }<br />staticvoidWriteVehicleDetails(dynamicvehicleobject)<br /> {<br />Console.WriteLine("The make of the vehicle is {0}", vehicleobject.Make);<br />Console.WriteLine("The color of the vehicle is {0}", vehicleobject.Color);<br /> }<br /> }<br />}<br />
  44. 44. ExpandoObject – CONT…<br />Can add methods at runtime - using lambda expressions. <br />Example: add method ChangeVehicleColor() to ExpandoObject - that changes color of the vehicle to white<br />dynamic Vehicle = newExpandoObject();<br />Vehicle.Make = "Ford";<br />Vehicle.Model = "Endeavour";<br />Vehicle.Engine = "4 cylinder";<br />Vehicle.Color = "Black";<br />Vehicle.ChangeVehicleColor = (Action)(() => {Vehicle.Color="White";});<br />WriteVehicleDetails(Vehicle);<br />Vehicle.ChangeVehicleColor();<br />WriteVehicleDetails(Vehicle);<br />
  45. 45. ExpandoObject – CONT…<br />expando object also implements the generic IDictionaryinterface<br />So you can enumerate the members of the object, if need.<br />dynamic vehicle = newExpandoObject();<br />vehicle.Make = "Cultus";<br />vehicle.Model = "2008";<br />vehicle.Engine = "4 cylinder";<br />vehicle.Color = "Silver";<br />EnumerateMembers(vehicle);<br />=============================<br />staticvoidEnumerateMembers(dynamicvehicleObject)<br />{<br />foreach (var property in (IDictionary<String, Object>)vehicleObject)<br /> {<br />Console.WriteLine(property.Key + ": " + property.Value);<br /> }<br />}<br />
  46. 46. DynamicObject<br />Provides a base class for specifying dynamic behavior at run time. This class must be inherited from; <br />User cannot instantiate DynamicObjectdirectly while ExpandoObject can.<br />The DynamicObject class - define which operations can be performed on dynamic objects and howto perform those operations<br />MSDN Example: http://msdn.microsoft.com/library/system.dynamic.dynamicobject.aspx<br />InterstingOppertunity: Receiver Object have an opportunity to inject it self into binding at runtime<br />So Object can determine the semantics of any dynamic operation (like dynamic method call) –TryInvokeMemberknows how to handle it?<br />
  47. 47. My Dynamic Object Implementation<br />Caller Code<br />dynamic d = newMyDynamicObject(); <br />d.Bar("Baz", 3, d);<br />So the call to Bar <br />Compiler don’t know anything at compile time<br />Run time, the object itself is asked what to do with this call to Bar. <br />That’s what TryInvokeMember knows how to handle.<br />Definition of My Dynamic class<br />classMyDynamicObject : DynamicObject<br />{<br />publicoverrideboolTryInvokeMember(InvokeMemberBinder binder, object[] args, outobject result)<br /> {<br />Console.WriteLine("Method: {0}", binder.Name);<br />foreach (var arg in args)<br /> {<br />Console.WriteLine("Argument: {0}", arg);<br /> }<br />result = args[0];<br />returntrue;<br /> }<br />}<br />Output of this code is:<br />Method: Bar <br />Argument: Baz<br />Argument: 3 <br />Argument: MyDynamicObject<br />
  48. 48. Usage<br />The Expando object is interoperable between different framework languages. So it is an obvious choice in situations where you have to pass objects between different framework languages that support the DLR interoperability model (IronPython, IronRuby).<br />The Dynamic object is a good choice for interacting with COM interops. <br />Useful to also be used with scripting objects (HTML DOM from Sliverlight).<br />If these two objects don’t do the trick for you, remember you can always create your own dynamic objects by implementing the IDynamicMetaObjectProviderinterface.<br />
  49. 49. BLOGS <br />http://blogs.msdn.com/b/samng/archive/tags/dynamic/<br />http://blogs.msdn.com/b/cburrows/archive/tags/dynamic/<br />
  50. 50. The Phantom Method<br />Rule of thumb:<br />Everything is convertible to dynamic – Implicit Conversion<br />Dynamic is not convertible to anything – Explicit Conversion or Assignment Conversion<br />
  51. 51. phantom method<br />publicclassC<br />{<br />publicvoid Foo(int x) { }<br />staticvoid Main()<br /> {<br />dynamic d = 10;<br />Cc = newC();<br />c.Foo(d);<br /> }<br />}<br />c.Foo(d) call contain dynamic, where assignment conversion is needed. <br />Foo(int) is not suffucent. Foo(dynamic) overload is needed<br />
  52. 52. phantom method<br />In each of these special situations compiler generates all the surrounding DLR code that prompts a runtime conversion.<br />The special situations in question are the following:<br />Overload resolution - c.Foo(d)<br />Assignment conversion - C c = d<br />Conditionals - if (d)<br />Using clauses - using (dynamic d = ...)<br />Foreach - foreach (var c in d)<br />Where c is static while d dynamic variable<br />
  53. 53. Overload resolution – phantom method<br />Since dynamic (d) is not convertible to anything (int), however, since we've got a dynamically typed argument, we really want the overload resolution for this call to be bound dynamically. Enter the phantom method.<br />The phantom method is a (overload) method which is introduced into the candidate set that has the same number of parameters as the number of arguments given, and each of those parameters is typed dynamic.<br />C.Foo(d) will bind to this Phantommethod Foo(dynamic), not Foo(int).<br />
  54. 54. phantom method<br />If compiler detects C.Foo(d) taking dynamic as parameter<br />It genertaes two overloads: <br />Foo(int) and Foo(dynamic). <br />The first overload fails because dynamic is not convertible to int. The second, the phantom, succeeds and so we bind to it.<br />Once a call is bound to the phantom overload, the compiler knows to generate the correct DLR magic to signal dispatching the call at runtime.<br />Question remains: when does the phantom overload not generated?<br />
  55. 55. phantom method<br />The phantom will be introduced if:<br />All of the non-dynamic arguments are convertible to their respective parameters.<br />At least one of the dynamic arguments is not convertible to its respective parameter.<br /> It would be possible for a call containing a dynamic argument to be dispatched statically instead of dynamically<br />
  56. 56. phantom method<br />publicclassC<br />{<br />publicvoid Foo(int x, dynamic y) { ... }<br />staticvoid Main()<br /> {<br />Cc = newC();<br />dynamic d = 10;<br />c.Foo(10, d);<br /> }<br />}<br />No phantom overload created in candidate set<br />initial binding pass and overload resolution behave like normal - despite the occurrence of a dynamic parameter<br />
  57. 57. Advanced Dynamic Limitations <br />
  58. 58. Mutating values Types using dynamic<br />dynamicd = 10;<br />d++;<br />Console.WriteLine(d); //d=11<br />If right side is value type then dynamic behave like and object and boxing takes place.<br />Variable d contains boxed copy of integer value<br />At runtime, ++ operator on d means unbox first into integer, then increment unboxed value, but value is not copied back inside box. Problem … because .Net/CLR have no ability on ref returns <br />Solution: There is an expression tree that performs an unbox and modifies the boxed value, and puts that value back into the box, allowing you to mutate the boxed values of these things.<br />
  59. 59. Nested structmutation<br />Extending last issue on value type, if any of the dotted expressions were to bind to a value type, that value will be boxed (and hence a copy would be made), and further dots into it would be made on the copy of the value, and not the initial value as would be expected. <br />Introduced bug in following example <br />
  60. 60. Nested structmutation - Example<br />publicstructS<br />{<br />publicint i;<br />} <br />publicclassD<br />{<br />publicSs;<br />publicvoid Execute()<br /> {<br />dynamic d = newD();<br />d.s = default(S);<br />d.s.i = 10;<br />Console.WriteLine(d.s.i);<br /> }<br />}<br />d.s.i will print 0 ???<br />
  61. 61. Base calls<br />There is a restriction in the CLR that prevents the compiler from generating non-virtual calls on virtual methods. This means that there is no way to call a base overload dynamically. This means that one cannot call a base call with any dynamically typed arguments, as it will trigger a dynamic binding.<br />
  62. 62. Explicitly implemented interface methods not supported<br />Interfaces are really compile time constructs, and have no runtime representation, explicitly implemented interface members get lost.<br />interfaceIFoo<br />{<br />void M();<br />}<br />classC : IFoo<br />{<br />voidIFoo.M() { }<br />}<br />C.M() is never callable from dynamic.<br />
  63. 63. No phantom for private<br />The down side of this scenario is that you could make a call with a static receiver to a private method that you know you can access from your context, but because a dynamic argument is given, the runtime binder will prevent you from calling the method.<br />publicclassC<br />{<br />privatevoid M(int x) { }<br />staticvoid Main()<br /> {<br />dynamic d = 10;<br />Cc = newC();<br />c.M(d);<br /> }<br />}<br />Complier will succeed because c.M() is accessiblein Main. <br />Since argument is dynamic, call is resolved at runtime, <br />Runtime binder have public only policy, so it will not generate Phantom overload with signature M(dynamic). <br />So overload resolution will not bind to the method<br />
  64. 64. More interesting scenarios<br />
  65. 65. Static or dynamic?<br />publicclassC<br />{<br />staticvoid Main()<br /> {<br />Cc = newC();<br />dynamic d = 10;<br />c.Foo(d, 10); // (1) Static Operation<br />d.Foo(10, 10); // (2) Dynamic Operation<br /> }<br />publicvoid Foo<T, S>(T x, S y) { }<br />}<br />The first call is a statically known receiver with a dynamically typed argument. <br />The second is a dynamically typed receiver with a statically known argument.<br />
  66. 66. Compiler ignores type inference of parameter type (and constraints)<br />Compiler assumes it is convertible at compile time, so skipping type inference may result unexpected results<br />publicclassC<br />{<br />staticvoid Main()<br /> {<br />Cc = newC();<br />dynamic d = 10;<br />c.Foo(10, d);<br /> }<br />publicvoid Foo<T>(T t, int x) where T : class { }<br />}<br />Compiler currently allow this call to compile successfully and fail at runtime!<br />Bug in Type Inference algorithm<br />
  67. 67. A complex scenario<br />publicinterfaceIAnimal { }<br />publicinterfaceIWatcher<in T> { } //Contravariant in T<br />publicclassWatcher<T> : IWatcher<T> { }<br />publicclassC<br />{<br />staticvoid Main(string[] args)<br /> {<br />Cc = newC();<br />IWatcher<Giraffe> a = newWatcher<Giraffe>();<br />IWatcher<Monkey> b = newWatcher<Monkey>();<br />dynamic d1 = 10;<br />dynamic d2 = newWatcher<Mammal>();<br />IWatcher<dynamic> d3 = newWatcher<dynamic>();<br />c.Bar(a, b, d1); // (1)<br />c.Bar(a, b, d2); // (2)<br />c.Bar(a, b, d3); // (3)<br /> }<br />publicvoid Bar<T>(IWatcher<T> w1, IWatcher<T> w3, IWatcher<T> w2) where T : IAnimal { }<br />}<br />publicclassMammal : IAnimal { }<br />publicclassGiraffe : Mammal { }<br />publicclassMonkey : Mammal { }<br />
  68. 68. Analysis of Example<br />In the first call, this is all fine and good - runtime type inference would also fail on the call. Even 10 is not Ianimal – but belief is suspended for dynamic.<br />However, the second call will succeed at runtime! Because the runtime type of d2 is Watcher<Mammal>, Mammal is added to the candidate set. And because IWatcher is covariant on T, choosing T to be Mammal satisfies argument convertibility for each of the three arguments<br />The third call will fail at compile time, because the candidate set for T is {Giraffe, Monkey, dynamic}, and T is not marked inconclusive. Type inference will infer T to be dynamic, since it is the common base class and IWatcher is covariant. However, constraint checking will fail, since dynamic is not an IAnimal.<br />
  69. 69. Language Interoperability<br />Calling from/to .NET the dynamic objects written in <br />IronPython<br />IronRuby<br />
  70. 70. IronPython Installation<br />http://ironpython.net/<br />http://ironpython.codeplex.com/releases/view/54498<br />Iron Python V2.7 - download and install <br />Open-source implementation of the Python programming language which is tightly integrated with the .NET Framework.<br />DLLs path is C:Program FilesIronPython 2.7<br />IronPython.dll<br />IronPython.Modules.dll<br />Microsoft.Scripting.dll<br />Microsoft.Scripting.Core.dll<br />
  71. 71. Invoke IronPython from C#<br />Instantiating the IronPython object from C#4 - using dynamic<br />Steps:<br />Ensure IronPython installed<br />Create simple console application<br />Reference DLLs from installed directory<br />Write hello.py script<br />Use dynamic to create and call IronPython method<br />Hello.py<br />class Hello:<br />def __init__(self):<br /> pass<br />def add(self, x, y):<br /> return (x+y)<br />
  72. 72. Invoke IronPythonfrom C#<br />var runtime = Python.CreateRuntime();<br />var scope = runtime.ExecuteFile(@"....scriptshello.py");<br />var ops = runtime.Operations;<br />varpythonType = scope.GetVariable("Hello");<br />dynamic instance = ops.CreateInstance(pythonType);<br />var value = instance.add(10, 20); //Result = 30<br />Console.WriteLine(value);<br />
  73. 73. Invoke C# “Dynamic Object” from C#/IronPython<br />publicclassMyDynamicObject : DynamicObject<br /> {<br />publicvoid Foo()<br /> {<br />Console.WriteLine("Foo() Called");<br /> }<br />publicoverrideDynamicMetaObjectGetMetaObject(System.Linq.Expressions.Expression parameter)<br /> {<br />Console.WriteLine("GetMetaObject() Called");<br />returnbase.GetMetaObject(parameter);<br /> }<br />publicoverrideboolTryInvokeMember(InvokeMemberBinder binder, object[] args, outobject result)<br /> {<br />Console.WriteLine("TryInvokeMember() Called");<br />returnbase.TryInvokeMember(binder, args, out result);<br /> }<br />publicoverrideboolTryGetMember(GetMemberBinder binder, outobject result)<br /> {<br />Console.WriteLine("TryGetMember() Called");<br />returnbase.TryGetMember(binder, out result);<br /> }<br />}<br />(Cont.….)<br />
  74. 74. Invoke C# “Dynamic Object” from C#/IronPython<br />publicstaticvoid Execute()<br />{<br /> dynamic myDynamicObject = newMyDynamicObject();<br />//first tey calling this object from C#, it should call Foo() and they try to call MissingMethod();<br />Console.WriteLine("C# Test...");<br />try<br /> {<br />myDynamicObject.Foo();<br />myDynamicObject.MissingMethod();<br /> }<br />catch (Exception ex)<br /> {<br />Console.WriteLine("Got C# exception: " + ex.Message);<br /> }<br />ScriptEnginepythonEngine = Python.CreateEngine();<br />ScriptScopescriptScope = pythonEngine.CreateScope();<br />stringpythonScript = SetPythonScript();<br />ScriptSource script = pythonEngine.CreateScriptSourceFromString(pythonScript, SourceCodeKind.Statements);<br />scriptScope.SetVariable("myDynamicObject", myDynamicObject);<br />//Now do the same thing from python, I expect to get the same behaviour as from C# <br />Console.WriteLine("rnScript Test...");<br />try<br /> {<br />script.Execute(scriptScope);<br /> }<br />catch (Exception ex)<br /> {<br />Console.WriteLine("Got script exception: " + ex.Message);<br /> }<br />}<br />staticstringSetPythonScript()<br />{<br />string s = "";<br /> s += "import clr" + "rn";<br /> s += "clr.AddReference('mscorlib')" + "rn";<br /> s += "myDynamicObject.Foo();" + "rn";<br /> s += "myDynamicObject.MissingMethod();" + "rn";<br />return s;<br />}<br />
  75. 75. IronRuby Installation<br />http://www.ironruby.net/<br />http://ironruby.codeplex.com/releases/view/25901<br />Iron Ruby V1.0 - download and install <br />Open-source implementation of the Ruby programming language which is tightly integrated with the .NET Framework.<br />DLLs path is C:Program Files (x86)IronRuby 1.0v4bin<br />IronRuby.dll<br />IronRuby.Libraries.dll<br />IronRuby.Libraries.Yaml.dll<br />Microsoft.Dynamic.dll<br />Microsoft.Scripting.Debugging.dll<br />Microsoft.Scripting.dll<br />Microsoft.Scripting.Silverlight.dll<br />System.Numerics.dll<br />
  76. 76. Problem with Framework Designers<br />Dynamic <br />Lacks documentation<br />Lack compile-time type checking<br />Lack Performance<br />Losing IntelliSense<br />
  77. 77. Lacks documentation<br />Severe lack of documentation. The entire application's architecture exists in the mind of the person (or persons) who wrote it. <br />At least with strong-typing, you can go see what the object does via its class definition. <br />With dynamic-typing, you must infer the meaning from it's use, at best. At worst, you have NO IDEA what the object is. It's like programming everything in JavaScript<br />
  78. 78. Lack compile-time type checking<br />>>Dynamic Version<br />publicdynamic Foo(dynamic other)<br />{<br />dynamic clone = other.Clone();<br />clone.AssignData(this.Data);<br />return clone;<br />}<br />>>Typed Version<br />public T Foo<T>(T other) where T : ICloneable, IAssignData<br />{<br /> T clone = (T)other.Clone();<br />clone.AssignData(this.Data);<br />return clone;<br />} <br />Critic: First one has no static type info, no compile time checking, it's not self documenting, no type inference so people will be forced to use a dynamic reference at the call site to store the result, leading to more type loss<br />
  79. 79. Don’t Use Blindly<br />Answer: <br />Use dynamic-only-when-necessary and var-at-all-other-times<br />Purpose of dynamic include<br />interoperability with dynamic languages and platforms such as COM/C++ and DLR/IronPython/IronRuby<br />turning C# itself implementing IDynamicObject<br />
  80. 80. Very Bad Performance<br />If dynamicusage can be avoided, it should be avoided.<br />Statistical performance study<br />dynamic c = 10; int b = c * c; <br />Above code is nice and very easy to read but very slow.<br />Comparisons:<br />Using regular reflection, you can't use defined operators. <br />About 10,000 times slower than a regular multiplication <br />About 100 times slower than an ICalculatorinterface with a Multiply method<br />Useful Link: http://blogs.msdn.com/b/lucabol/archive/2009/02/05/simulating-inumeric-with-dynamic-in-c-4-0.aspx<br />
  81. 81. Generated Code – for interested ones<br />dynamic c = 10; int b = c * c; <br />
  82. 82. HTML DOM<br />If you write Silverlight applications, you might have the need today or in the future to access the HTML DOM containing your Silverlight control. C# dynamic programming makes this task easier.<br />
  83. 83. HTML DOMExpects Dynamic Dispatch from JScript<br />JScript:<br />var loc = new VELatLong(latitude, longitude);<br />var pin = map.AddPushpin(loc);<br />pin.SetTitle(title);<br />pin.SetDescription(description);<br />map.SetCenterAndZoom(loc, 7);<br />C# 3.0 <br />(Silverlight):<br />ScriptObject loc = win.CreateInstance( "VELatLong", lat, long)<br />ScriptObject pin = (ScriptObject)map.Invoke("AddPushpin", loc);<br />pin.Invoke("SetTitle", title);<br />pin.Invoke("SetDescription", description);<br />map.Invoke("SetCenterAndZoom", loc, 7);<br />dynamic loc = win.New.VELatLong(latitude, longitude)<br />var pin = map.AddPushpin(loc);<br />pin.SetTitle(title);<br />pin.SetDescription(description);<br />map.SetCenterAndZoom(loc, 7);<br />C# 4.0 <br />(Silverlight):<br />
  84. 84. Runtime semantics/sequence of dynamic binding<br /><ul><li>If the receiver is a dynamic object – i.e., implements IDynamicMetaObjectProvider– the object itself programmatically defines the resolution of the operations performed on it.
  85. 85. Otherwise the operation gets resolved at runtime in the same way as it would have at compile time, using the runtime type of any constituent value statically typed as dynamic and the compile time type of any other constituent value.
  86. 86. If a constituent value derives from a literal, the dynamic binding is able to take that into account. For instance, some conversions are available only on literals.
  87. 87. If a constituent value of static type dynamic has the runtime value null, it will be treated as if the literal null was used.
  88. 88. Extension method invocations will not be considered – the set of available extension methods at the site of the call is not preserved for the runtime binding to use.
  89. 89. If the runtime binding of the operation succeeds, the operation is immediately performed,otherwise a runtime error occur</li></li></ul><li>COM Interfaces - rewritten<br />Introp assemblies are rewritten to support named parameter and dynamic<br />
  90. 90. Online Resources<br />C# Future Download Page:<br />http://code.msdn.microsoft.com/csharpfuture<br />SilverlightStarter project available in the CSharpDynamicSamplesdownload<br />VB Future Download Page:<br />http://code.msdn.microsoft.com/vbfuture<br />IronPython CTP Release:<br />http://go.microsoft.com/fwlink/?LinkId=129196<br />And to all sources on Blogs, Forums and pages – don’t track usually<br />
  91. 91. About Me<br />Basharat Hussain<br />Solution Architect<br />TEO (Pvt.) Ltd. 3rd Floor, Hassan Arcade, F-11 Markaz, Islamabad, Pakistan<br />Mail: basharat@live.com<br />Blog: http://basharatspace.blogspot.com/<br />
  92. 92. Q&A<br />

×