1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình .net 4.0 và visual studio 2010 part 8 doc

6 332 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 100,1 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

IDynamicMetaObjectProvider IDynamicMetaObjectProvider is an important interface in the dynamic world that represents an object that has operations bound at runtime.. You can use this in

Trang 1

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";

Trang 2

This will generate the following IL:

.method private hidebysig static void Main(string[] args) cil managed

{

entrypoint

// Code size 8 (0x8)

maxstack 1

locals init ([0] string d)

IL_0000: nop

IL_0001: ldstr "What do I look like in IL"

IL_0006: stloc.0

IL_0007: ret

} // end of method Program::Main

Now we will alter d to be of type dynamic:

dynamic d;

d = ”What do I look like in IL?”;

This will generate the following IL:

.method private hidebysig static void Main(string[] args) cil managed

{

entrypoint

// Code size 8 (0x8)

maxstack 1

locals init ([0] object d)

IL_0000: nop

IL_0001: ldstr "What do I look like in IL"

IL_0006: stloc.0

IL_0007: ret

} // end of method Program::Main

Note how the line locals init ([0] object d) replaces locals init ([0] string d) in the dynamic example This is probably what you might expect to happen, but let’s take another more complex example Create a new console application called Chapter3.DynamicComplex and add the following code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Chapter3.DynamicComplex

{

class Program

{

static void Main(string[] args)

{

TestClass t = new TestClass();

t.Method1();

Trang 3

public class TestClass

{

public void Method1() { }

}

}

Compile the application and examine the IL using ILDASM You will find something similar to the following:

.method private hidebysig static void Main(string[] args) cil managed

{

entrypoint

// Code size 15 (0xf)

maxstack 1

locals init ([0] class Chapter3.DynamicComplex.TestClass t)

IL_0000: nop

IL_0001: newobj instance void Chapter3.DynamicComplex.TestClass::.ctor()

IL_0006: stloc.0

IL_0007: ldloc.0

IL_0008: callvirt instance void Chapter3.DynamicComplex.TestClass::Method1()

IL_000d: nop

IL_000e: ret

} // end of method Program::Main

However, if we alter our t variable to the following:

dynamic t = new TestClass();

t.Method1();

then the IL will look very different (I have removed some of the IL to save some trees):

class [mscorlib]System.Collections.Generic.IEnumerable`1<class

[Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)

IL_003a: call class [System.Core]

System.Runtime.CompilerServices.CallSite`1<!0> class

[System.Core]System.Runtime.CompilerServices.CallSite`1

<class [mscorlib]System.Action`2<class

[System.Core]System.Runtime.CompilerServices.CallSite,object>>::Create(class

[System.Core]System.Runtime.CompilerServices.CallSiteBinder)

IL_003f: stsfld class [System.Core]System.Runtime.CompilerServices

.CallSite`1<class [mscorlib]System.Action`2<class

[System.Core]System.Runtime.CompilerServices.CallSite,object>>

Chapter3.DynamicComplex.Program/'<Main>o SiteContainer0'::'<>p Site1'

IL_0056: callvirt instance void class [mscorlib]System.Action`2<class

[System.Core]System.Runtime.CompilerServices.CallSite,object>::Invoke(!0, !1)

Whoa, what is happening here? Well the short answer is that calls to dynamic methods are sent to

the Dynamic Language Runtime for resolution It is time to take a look into how the DLR works

Trang 4

Dynamic Language Runtime (DLR)

The Dynamic Language Runtime (DLR) is behind all the cool dynamic functionality and sits just above the core NET framework The DLR’s job is basically to resolve calls to dynamic objects, cache dynamic calls making them as quick as possible, and enable interaction between languages by using a common format The DLR has actually been around a while, and was included in earlier versions of Silverlight You can even view the source code behind the DLR at: http://dlr.codeplex.com Note that this version contains a number of features not present in the framework version

When discussing the DLR we need to understand five main concepts:

• Expression trees/Abstract Syntax Trees (AST)

• Dynamic Dispatch

• Binders

• IDynamicObject

• Call Site Caching

Expression/Abstract Syntax Trees (AST)

Expression trees are a way of representing code in a tree structure (if you have done any work with LINQ, you may have come across this before with the Expression class) All languages that work with the DLR represent code in the same structure allowing interoperability

Dynamic Dispatch

Dynamic Dispatch is the air traffic control center of the DLR, and is responsible for working out what to

do with dynamic objects and operations and sending them to the appropriate binder that takes care of the details

Binders

Binders resolve classes from dynamic dispatch .NET 4.0 currently supports the following binder types:

• Object Binder NET (uses Reflection and resolved our earlier example to type string)

• JavaScript binder (IDynamicObject)

• IronPython binder (IDynamicObject)

• IronRuby binder (IDynamicObject)

• COM binder (IDispatch)

Note that dynamic objects can resolve calls themselves without the DLR’s assistance (if they implement IDynamicObject), and this method will always be used first over the DLR’s dynamic dispatch mechanism

Trang 5

IDynamicObject

Sometimes you will want objects to carry out resolution themselves, and it is for this purpose the

IDynamicObject exists Normally dynamic objects are processed according to type, but if they implement the IDynamicObject interface then the object will resolve calls itself IDynamicObject is used in IronRuby and IronPython

Callsite Caching

Resolving objects is an expensive operation, so the DLR caches dynamic operations When a dynamic

function or operation is performed, the DLR checks to see if it has been called already (Level 0 cache) If

it hasn’t, then the 10 most recently used dynamic methods for this callsite will be checked (Level 1

cache) A cache is also maintained across all target sites with the same binder object (Level 2 cache)

IronPython

A similar process to this is used when languages such as IronPython interact with NET What follows is a high-level version of how the DLR processes an IronPython file:

1 The IronPython file is first compiled into intermediary IronPython AST (Not all languages will necessarily create an intermediary AST, but IronPython’s developers decided this would be a

useful step for creating language-specific tools.)

2 The IronPython AST is then mapped to the generic DLR specific AST

3 The DLR then works with the generic AST

For a detailed look at how this works with Iron Python please refer to: http://msdn.microsoft.com/ en-us/magazine/cc163344.aspx

As all languages end up being compiled into the same common AST structure, it is then possible for interaction between them

Embedding Dynamic Languages

One use of dynamic languages that really excites me is the ability to embed them within your C# and

VB.NET applications One possible use would be to use them to define complex business rules and logic

Dynamic languages are often utilized in computer game construction to script scenarios and logic (such as how Civilization IV utilizes Python) Let’s take a look at how to work with IronPython in a C# application

Calling IronPython from NET

The following example passes a value into a simple IronPython script from C# Note that you should

have installed IronPython from http://ironpython.codeplex.com/ Now add a reference to

IronPython.dll and Microsoft.Scripting.dll (at the time of writing these don’t show up on the main

Add Reference window but are located at C:\Program Files (x86)\IronPython 2.6)

Trang 6

using Microsoft.Scripting;

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

namespace Chapter3.PythonExample

{

class Program

{

static void Main(string[] args)

{

ScriptEngine pythonEngine = Python.CreateEngine();

ScriptScope scope = pythonEngine.CreateScope();

string script = @"print ""Hello "" + message";

scope.SetVariable("message", "world!");

ScriptSource source =

scope.Engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements); source.Execute(scope);

Console.ReadKey();

}

}

}

IronPython is already in use in two real-world applications, so let’s take a look at these now

Red Gate Reflector Add-In

Many of you will be familiar with the tool Reflector (www.red-gate.com/products/reflector/) Reflector allows you to explore an assembly and view the IL code within it C# MVP Ben Hall developed an add-in (Methodist) to Reflector that allows you to actually call the classes and methods within the type you are exploring using Iron Python For more information please consult: http://mail.simple-talk.com/ dotnet/.net-tools/methodist-make-.net-reflector-come-alive-with-ironpython/

ResolverOne

One of the best know uses of IronPython is for ResolverOne (http://www.resolversystems.com)

ResolverOne is an application that allows you to work with Excel’s objects using IronPython See Figure 3-3

Ngày đăng: 01/07/2014, 21:20

TỪ KHÓA LIÊN QUAN