Tải bản đầy đủ (.pdf) (5 trang)

Lập trình .net 4.0 và visual studio 2010 part 7 pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (117.47 KB, 5 trang )

CHAPTER 3  LANGUAGE AND DYNAMIC CHANGES

51
Further Reading
Variance is a difficult subject, so for more information please refer to the following blogs and book:
• />contravariance-in-visual-studio-2010.aspx

default.aspx
• Skeet, Jon. (2008) C# in depth. Manning Publications.
Dynamic Enhancements
The new dynamic functionality in .NET 4.0 allows us to work with types not known at compile time in an
intuitive and easy to read way. Many of you may be wondering what can the dynamic changes do for
you. The dynamic changes allow us to do the following:
• Write more readable code with fewer casting operations.
• Create new languages to utilize the .NET Framework, such as IronPython and
IronRuby. Additionally, .NET’s dynamic architecture allows these languages to
automatically benefit from future framework advances.Utilize other dynamic
languages and their libraries.
• Utilize other dynamic languages and their libraries from C# and VB.NET.
• Introduce customization/scripting and debugging/querying functionality within
our applications.
• Work with COM objects more easily. Microsoft Office COM is going to be around
for some time whether you like it or not.
• Many other cool uses we haven’t thought of yet.
Can’t We Do This Kind of Thing Already in .NET?
.NET has a number of classes and methods for working with types not known at compile time, such as
reflection and expression trees. However, if you have spent much time with these technologies, you will
known that they can make for some clunky and difficult to read code. As I will show you, the dynamic
enhancements can make your life much easier.
Before we look at how to use the dynamic enhancements, we need to understand the difference
between statically and dynamically typed languages.


Static Languages
In a statically typed language, such as C# or C, the compiler checks you are using types correctly at
compile time. Compilation will fail, for example, if you assign a string to an integer or misspell a variable
name. Statically typed languages can catch simple syntax errors and typos during development and as
the compiler knows the types it will be working with static languages generally run quicker then dynamic
languages (next) as optimizations can be performed on code.
CHAPTER 3  LANGUAGE AND DYNAMIC CHANGES

52
Dynamic Languages
In contrast, dynamic languages, such as JavaScript, Python, Lisp, and Ruby, do not perform type checks
on code until runtime. This can be a big advantage if you don’t know the type of object you will be
working with at compile time. These features can also make it possible to perform some interesting code
tricks and reduce tedious casting operations if the language can work out how to use the type. Some
developers feel dynamic languages can help them develop and prototype applications much quicker,
and can be particularly suitable for testing and prototyping applications.
The main disadvantage of working with dynamic languages is they of course lack compile time
checks and generally have inferior performance when compared to static languages. When working with
dynamic languages, simple syntax errors and typos can stop your code working. I think anyone that has
done any web development has spent much time tracking down such an error in JavaScript with its very
helpful “object not set to an instance” message.
Dynamic Dangers
When working with dynamic types and the Dynamic Language Runtime (DLR) there are three
considerations you should bear in mind.
• IDE support is limited
• Generally, performance is poor (although precompilation is sometimes possible),
especially on the first call to a method where the DLR has not yet cached a method call.
• Using the DLR unnecessarily is not big or clever (more complexity = bad).
I’ll cover the DLR in detail later in this chapter.
Type Dynamic

.NET 4.0 introduces a new type dynamic that allows you to tell the compiler to resolve a variable’s type at
runtime. Somewhat paradoxically the keyword dynamic statically types an object as dynamic.
To declare an object as dynamic, prefix the variable name with the type dynamic:

dynamic myDynamic="Something";
Console.WriteLine(myDynamic.GetType().Name);
Console.ReadKey();

What type will be output on the second line? Dynamic, object?
For those of you who said String you are correct (now stop looking so smug); I will explain why this
is shortly.
Is dynamic the Same as Var?
No, dynamic is very different. When the var keyword is used the compiler infers the type of value you are
using and writes the appropriate code for you when you compile the application. Variables declared
using var benefit from type checks, Intellisense, and offer better performance than their dynamic
equivalent. Types declared as dynamic are evaluated at run time and do not have these benefits.
CHAPTER 3  LANGUAGE AND DYNAMIC CHANGES

53
Why Type Variables as Dynamic?
One advantage is that it can avoid some tedious casting and Reflection code. For example, let’s say we
want to create an instance of a type using a string and call a method on it at runtime. In our example we
will create a StringBuilder instance and call the Append method on it using Reflection:

object UsingReflection =
Activator.CreateInstance(Type.GetType("System.Text.StringBuilder"));
Type ObjectType = UsingReflection.GetType();
//Append has many overloads so we need to tell reflection which type we will use
Type[] TypeArray = new Type[1];
TypeArray.SetValue(typeof(string), 0);

var ObjectMethodInfo=ObjectType.GetMethod("Append", TypeArray);
ObjectMethodInfo.Invoke(UsingReflection, new object[] { "alex" });
Console.WriteLine(
ObjectType.GetMethod("ToString", new Type[0]).Invoke(UsingReflection, null)
);
Console.ReadKey();

By using dynamic, however, we can make this simpler and more readable (and I know which bit of
code I could remember):

dynamic usingDynamic = Activator.CreateInstance(Type.GetType("System.Text.StringBuilder"));
usingDynamic.Append("Hello");
Console.WriteLine(UsingDynamic.ToString());
Console.ReadKey();

NOTE
Technically you could do something similar in VB.NET by declaring UsingDynamic as object, so arguably
VB.NET could be considered to contain dynamic functionality already.
Consider using dynamic types in the following situations:
• When working with COM, dynamic types allow a more concise syntax (we saw this
earlier). Let the DLR do the work figuring out how to bind your method and
property calls.
• When interacting with a dynamic language such as IronPython.
• When working with objects that have changing structures, such as HTML or XML
documents (we will look at this shortly).
System.Dynamic.ExpandoObject
ExpandoObject is a strange new beast in the .NET Framework that allows you to add and remove
properties, methods, and events at runtime. The following example demonstrates how to add two new
values and a method:


CHAPTER 3  LANGUAGE AND DYNAMIC CHANGES

54
using System.Dynamic

dynamic MyExpando = new ExpandoObject();

MyExpando.Value1 = "new value 1";

MyExpando.Value2 = "new value 2";


MyExpando.DoSomething = new Action(() => Console.WriteLine("DoSomething called"));

Console.WriteLine(MyExpando.Value1);

MyExpando.DoSomething();


Console.ReadKey();

ExpandoObject could be used for wrapping data and making it easier to work with and is included for
interoperability with dynamic languages that support this concept.
System.Dynamic.DynamicObject
.NET 4.0 introduces a new class called DynamicObject that allows the definition of runtime behavior,
offering a much greater level of control than ExpandoObject. It is important to note that DynamicObject is
never instantiated directly but must be inherited from.
DynamicObject again is great for wrapping data and making it easier to work with, but offers a much
finer level of control than ExpandoObject. If you just need to define parameters at runtime you will
probably be adequately served by ExpandoObject (above) however DynamicObject allows you full control

over various operations performed.
The following example shows how to query an XML document using properties to create more
readable code:

using System.Dynamic;
using System.Xml.Linq;

class Program

{

static void Main(string[] args)

{

dynamic easierXML =
new EasierXML(@"<test><node1>Alpha</node1><node2>Beta</node2></test>");

Console.WriteLine(easierXML.node1);

Console.WriteLine(easierXML.node2);

Console.ReadKey();

}


public class EasierXML : DynamicObject

{


private XDocument _xml = new XDocument();



public EasierXML(string Xml)

{

this._xml = XDocument.Parse(Xml);

}


CHAPTER 3  LANGUAGE AND DYNAMIC CHANGES

55
public override bool TryGetMember(GetMemberBinder binder,
out object result)

{

string nodeName = binder.Name;

result = _xml.Element("test").Element(nodeName).Value;

return true;

}


}

}


In this example, the TryGetMember() method intercepts the call to .node1 and .node2, thus allowing
us to query the XML document and return the individual nodes.
IDynamicMetaObjectProvider
IDynamicMetaObjectProvider is an important interface in the dynamic world that represents an object that
has operations bound at runtime. Both ExpandoObject and DynamicObject implement this interface. You
can use this interface to add dynamic functionality to your own classes. IDynamicMetaObjectProvider
requires you to implement GetMetaObject(),(), which resolves binding operations (for example, method or
property invocation on your object).
Dynamic Limitations
When working with dynamic objects, there are a number of constraints you should be aware of:
• All methods and properties in classes have to be declared public to be dynamically
accessible.
• You cannot use the DLR to create classes in C# or VB.NET. Apparently, the DLR
does allow you to create classes, but this cannot be expressed using C# or VB.NET.
• Dynamic objects cannot be passed as arguments to other functions.
• Extension methods cannot be called on a dynamic object and a dynamic object
cannot be passed into extension objects.
Annoyingly, these restrictions stop you calling an extension method on a dynamic object.
Dynamic IL
You may be wondering what code the C# compiler generates when you use the dynamic keyword. Let’s
take a look at the IL that is generated using ILDASM for a simple console application that declares and
initializes a string:

string d;
d = "What do I look like in IL";


×