Docstoc

Reflection

Document Sample
Reflection Powered By Docstoc
					Reflection
2                         Reflection

Objectives




             Objectives
             The objective of this module is to provide an introduction
             into the Reflection capabilities of the common language
             runtime of Microsoft .NET. Reflection allows applications
             to explore their own structure at runtime.
             Many internal mechanisms inside the .NET Framework
             are driven by this structural information (called
             “Metadata”) and, thus, Reflection is one of the most
             fundamental aspects of the Common Language Runtime
             environment that you need to understand to explore the
             advanced features of .NET.
             What You Will Learn
                The core concepts of Reflection and .NET Metadata
                The System.Type class
                The member information classes of System.Type
                Creating code with System.Reflection.Emit
                               Reflection                                     3

Section 1: Overview




                      Section 1: Overview
                      In this first section we will look at what type information is
                      available and how it is made available in the “unmanaged
                      world” of COM. We will also look at some of the lessons
                      that have been learned from the experience with this
                      model and how this led in the new Metadata model of
                      .NET
                      Looking back: Automation
                      What’s wrong with that?
                      .NET Reflection Core Concepts
4                                   Reflection

Section 1: Overview




                      Looking Back: Automation
                      Reflection is all about Metadata and the structural
                      composition of applications. Of course, this concept is not
                      new. Therefore we will first look back at how type
                      description and type exploration could be performed in the
                      COM world.
                      Type libraries contain type information
                      In COM, most type information is contained in type
                      libraries. A type library is a binary file, which is provided
                      alongside with or embedded in the server component.
                      Type libraries can be explored through the ITypeLib and
                      ITypeInfo interfaces and are generated by the MIDL
                      compiler.
                      Attributes describe behavior of elements
                      The type information contained in these libraries is
                      attributed. Each interface, method or argument can be
                      augmented with attributes, which describe their behavior.
                      These are for instance the [in] or [out] attributes for
                      method arguments, which define the directionality of
                      marshaling. Other attributes allow to distinguish between
                      simple instance methods and methods that are used to
                      set or gets property values. The interface identifier is also
                      associated with the interface declaration using an
                      attribute.
                      Dynamic Invocation using IDispatch
                      The COM "automation" model allows late binding through
                      the IDispatch interface. The IDispatch interface allows the
                      dynamic expiration of type descriptions, which the server
                      may either retrieve and expose from a type library or will
                      dynamically create at runtime. The type information that
        Reflection                                    5

is exposed through the IDispatch interface is structurally
identical to the information model of ITypeInfo.
Type system supports most popular simple types
The type system that can be used with COM and through
the ITypeInfo, ITypeLib and IDispatch interfaces supports
the most popular simple data types, but is very limited in
supporting complex types. Because COM is a binary
standard, types that require a certain in-memory
organization (like strings) are COM-native and need
special handling or care by the server and client
implementers.
Dynamic types using VARIANT
Dynamic types are available through the VARIANT data
type. Variants are COM's universal containers, which can
transport values of all native COM data types.
Arrays passed using SAFEARRAY
Arrays of values are past using the SAFEARRAY type.
The SAFEARRAY is special structure, which allows
passing multidimensional blocks of homogeneous types
between COM components.
Strings expressed as BSTR
COM strings are expressed as BSTR types, which is a
zero terminated string with two lead bytes that indicate the
length of the string.
6                                   Reflection

Section 1: Overview




                      What's wrong with that?
                      Automation client model favors VisualBasic
                      The main problem with automation is that the client model
                      clearly favors Visual Basic another rapid application
                      development languages, where the underlying runtime
                      can hide much of the complexity.
                      Automation server model favors C/C++
                      The server side, however, is better supported by low-level
                      languages such as C and C++, because only those allow
                      a level control that lets you leverage all features of the
                      COM automation infrastructure which can then be
                      exposed to and consumed by automation clients. This is
                      in line with original vision of automation, where Visual
                      Basic was thought to be used as a language that could
                      control but not necessarily implement large COM servers.
                      This has of course changed or while ago, but the bias in
                      the COM infrastructure is still visible.
                      ITypeInfo and IDispatch are way too complicated
                      Exploration of the ITypeInfo and IDispatch information is a
                      very complicated task.         There are a few dozen of
                      structures to deal with the navigation through the type
                      information is neither is straightforward nor easy. So
                      although quite a few aspects of attributed programming as
                      it is now promoted in the .NET world, is possible in COM
                      with type libraries and custom attributes that can be added
                      to those libraries. But because evaluating this type
                      information is a complicated and was never really seen a
                      serious option for most developers. A good example for
                      this extensibility are the custom type library attributes that
                      are available for COM+ and the Microsoft Transaction
        Reflection                                   7

Server, which allow you to flag components as
transactional in the IDL file, and when imported into
COM+ these attributes are being read and the
components are configured correctly.
Information model is limited, no support for complex types
Another problem is that the information model is too
limited. While it has been proven millions of times, that
the COM information and type model is sufficient for most
scenarios, the lack of ability to marshal complex types
through the dynamic binding interfaces has often lets the
implementation of wrapper interfaces around structures,
which should technically have been marshaled by value
and made available natively to the client application.
Doing so without implementing custom marshaling
through IMarshal (which is not a widespread skill or dare)
will result in objects being exposed by reference and
increased traffic between client and server.
SAFEARRAYs are a pain from C/C++
The SAFEARRAY type, which is COM's native array,
needs a lot of very special attention in C and C++
programs through a special API, which can only be
described as being a pain in terms of usability.
BSTRs are difficult to manage from C/C++
The BSTR string type is also problematic and a common
source of bugs in COM applications, because it looks
suspiciously like any other zero-terminated string but
requires special allocation and de-allocation functions.
Type information separate from code
Another issue is that the type information is separate from
the code. Just as you have "DLL hell" with multiple
versions of the same components on the same machine,
there exists a very related problem with multiple type
libraries for these different versions.
8                                   Reflection

Section 1: Overview




                      .NET Reflection Core Concepts
                      .NET reflection and its core concepts build on the
                      experience of the COM type library model. Applications
                      are able to evaluate the type information at runtime and
                      invoke services in a late bound fashion. The two core
                      elements that enable this are "Metadata" and .NET's
                      dynamic common type system.
                      Metadata
                      Metadata provides a single location for the type
                      information and code. In .NET assemblies of the entire
                      structural information about application is bundled
                      together with a description of its runtime behavior,
                      expressed in the Microsoft intermediate language. The
                      structural information describes the overall shape of
                      assemblies and modules into detail each data type and
                      class. Class methods and all other active entities are
                      stored with their call signature and return value types and
                      their MSIL code. MSIL is therefore really part of the
                      description of any method, because the actual code that is
                      executed at runtime is a compiled representation of the
                      MSIL in native machine code.
                      While the COM type library information is restricted to
                      those types for which inclusion in the library was explicitly
                      requested, Metadata is available and accessible for each
                      and every type that is being used in .NET managed code.
                      Every .NET types, from simple scalar types such as a
                      plain integer to complex classes can be queried for its
                      type. At runtime, data types are represented by special
                      .NET runtime class, System.Type. This class allows close
                      inspection of every aspect of a runtime data type. The
        Reflection                                     9

framework's ability to make type information available at
runtime through this class is what is called "reflection".
Dynamic Type System
The universal exploration of type information is enabled by
the dynamic common type system (CTS). All languages
that target the .NET framework share the CTS. The
language compilers automatically create the type
information stored in the Metadata, which can later be
read by applications written in any other language.
Because the underlying type system is now independent
of the implementation language used, the restricted type
model that we know from COM no longer applies and the
exchangeable type information is equivalent to the type
information used to build applications. Under the hood,
the type information exposed through reflection is
sometimes even richer than what can be expressed using
the intrinsic language elements of languages like C#.
The "Emit" part of reflection, which is covered in the
second part of this module allows types the extended (by
inheritance) or be entirely build at runtime. This allows for
the on the fly creation of new assemblies and modules
and in fact .NET compilers use .NET to emit .NET code.
10                                  Reflection

Section 2: Exploring Metadata




                    Section 2: Exploring Metadata
                    Before we start drilling into the basics of Reflection, a
                    word of advice especially for those who will actively
                    present this topic to an audience:
                    Reflection is one of the most fundamental technologies of
                    the .NET platform and, yet, at the same time it is very
                    simple to use on the surface. This section is likely one of
                    the longest discussions of a single class, System.Type,
                    among all modules in this kit, but because of its
                    fundamental importance it really deserves the space and
                    detail of the discussion. System.Type should be just as
                    present in the mind of every developer as System.Object,
                    because Reflection opens the doors to the power of
                    attributed programming and type-driven functionality.
                    Who are you?
                    What are you?
                    Anything special about you?
                    Now tell me what you have!
                    Types and Instances
                             Reflection                                   11

Section 2: Exploring Metadata




                    Metadata: Type Info at Runtime
                    The illustration in the associated slide unravels much of
                    the mystery of Reflection. Essentially, once you are able
                    to grasp what the slide is demonstrating, you have already
                    entirely understood what Reflection is all about.
                    In the illustration you see that the code in the method
                    “Save” invokes the method “GetType()” on the object’s
                    “this” self-reference.
                    This method is always available on any .NET class, since
                    it is a member of the fundamental System.Object class
                    that is the base for any managed code class, regardless
                    of whether you explicitly declared that inheritance
                    relationship. All .NET compilers will establish that
                    relationship automatically “under the hood”.
                    The method “GetType()” returns an instance of the
                    System.Type class, which encapsulates access to all
                    Metadata of the object you “asked”.
                    The System.Type instance will allow you to traverse into
                    all details of the type or class (excluding, specifically, the
                    IL code) and also explore the environment like the
                    implementing module and container assembly.
                    The following discussion will center on System.Type and
                    look at the capabilities of this single class in very much
                    detail.
12                               Reflection

Section 2: Exploring Metadata




                    Who are you?
                    Accessing metadata: System.Object.GetType()
                    To sum up what you could see on the diagram: Because
                    everything is essentially a class in .NET and all classes
                    are derived from System.Object, which exposes the
                    Reflection “gateway” GetType() as one of the most
                    fundamental mechanisms in .NET, you can reflect every
                    single type in .NET, including the simple, scalar types
                    such as plain integers.
                    Explicit language support for type metadata
                    Although this mechanism is intrinsic to every object, the
                    .NET languages have additional keywords and helpers to
                    use and access Metadata though Reflection. The issue
                    with GetType() is, of course, that it only works on active
                    instances and not on class expressions as such.
                    In C# and JScript.NET you can therefore use the intrinsic
                    typeof(classname) expression to obtain the Metadata for
                    the class without having to create an instance. The
                    alternative for Managed C++ and Visual Basic.NET is of
                    course to use the “System.Type.GetType(‘classname’)”
                    method, but at the price that you need to express the
                    class with it’s fully qualified namespace while you can just
                    use a scoped expression in C# or Jscript.NET (that is,
                    without the namespace qualifiers).
                    In Visual Basic.NET you can use the “TypeOf” operator as
                    part of an “If … Then … Else” expression to test whether
                    an arbitrary variable expression is of a certain class type.
        Reflection                                13

Determining Type Identity
Each type that you declare has a unique identity across
any assembly. Because of .NET’s ability to assign “strong
names” to assemblies to make their definition space
globally unique, each type indirectly also gains this
uniqueness quality. Furthermore, the mandatory
namespace use in .NET further eliminates the collision
potential.
If you want to determine whether two expressions are of
identical type, you can therefore directly compare their
type objects.
14                                Reflection

Section 2: Exploring Metadata




                    System.Type
                    The core of all things in Reflection is really System.Type
                    Access to metadata for any .NET type
                    Every instance of System.Type is a dynamically created
                    wrapper around the Metadata of certain class. When you
                    invoke “GetType()” on an object, the runtime will gather
                    the requested Metadata, stuff it into a fresh System.Type
                    instance and hand it to you.
                    Returned by System.Object.GetType()
                    Instances of the System.Type class are most prominently
                    returned by the System.Object.GetType() method as this
                    has been shown previously, but as you descend into the
                    depths of the .NET framework you will find that Type
                    objects are used quite often throughout the lower-levels of
                    the Framework hierarchy.
                    Allows drilling down into all facets of a type
                    The System.Type class will allow you to explore all facets
                    of a type like the type “category”, a class’ or structure’s
                    methods, constructors and their parameters and return
                    values. Furthermore, of course, all other aspects of such
                    types like properties, fields, events and delegates and, of
                    course, the namespace the class is located in can be
                    explored.
                            Reflection                                  15

Section 2: Exploring Metadata




                    What are you?
                    When we zoom in on the System.Type class you will find
                    that we can ask quite a few very precise and very simple
                    questions through its methods as this is shown on the
                    slide.
                    Covers all possible properties of a managed type
                    These very plain calls indeed expose all core information
                    of a managed type.
                    Very intuitive API, no "Parameter Hell"
                    The bottom line here is simplicity. You do not need to
                    haggle around with flags buried in bit-fields, but can just
                    ask a very readable and clear question and get a “yes” or
                    “no” response.
                    Especially to C/C++ developers this may look a bit too
                    verbose at first, but if you really go back into your own
                    code you will find that while you typically retrieve such
                    information encoded into a single bit-field (like a 32bit
                    unsigned integer), for instance when using the Win32 API,
                    you mostly end up testing the values individually by
                    isolating them from the set.
16                               Reflection

Section 2: Exploring Metadata




                    Anything special about you?
                    Here you have some of the more advanced “Is questions”
                    for the System.Type class.
                    Special Memory Layout?
                    For P/Invoke and COM/Interop purposes, structures may
                    be declared with special memory layout rules that define
                    exactly how the data of a structured is rendered into a
                    memory block when it is passed into and from unmanaged
                    code.      The     three    properties    “IsAutoLayout”,
                    “IsExplicitLayout” and “IsLayoutSequential” will tell you
                    whether the in-memory layout is automatic (managed) or if
                    any special rules apply.
                    Typically, there is little reason for you to query these
                    properties, because you will very likely not be able to
                    make too much use of that information. The existence of
                    these methods does, however, demonstrate how essential
                    Remoting is for the Framework itself. When an object is
                    passed to managed code, the P/Invoke and COM/Interop
                    layers will indeed use the information obtained through
                    Reflection to properly format the outgoing and incoming
                    binary data blocks.
                    COM Objects and Unmanaged Types?
                    You can also tell whether an object is really a proxy to a
                    COM object. There are a set of special rules such as
                    restrictions in implementation inheritance when integrating
                    COM classes into .NET applications or you may want to
                    explicitly release and discard the COM object from its
                    Runtime Callable Wrapper (RCW) and this is a way to tell
                    whether this applies to a certain object.
                             Reflection                                   17

Section 2: Exploring Metadata




                    Now tell me what you have!
                    Complex types have much more to offer and tell than their
                    name and fundamental properties. The “Get*” methods of
                    the System.Type provide access to the fields, properties
                    and methods of a managed type.
                    Finding and Exploring Members
                    For generic access to all members, independent of their
                    exact role, you can either use the “GetMembers()” method
                    to retrieve a complete array of MemberInfo structures (to
                    be explained in detail a bit later) or seek for a certain
                    member by name using the “FindMembers” method. If you
                    want to get only the fields or methods, you can use one of
                    the role-dependent access methods:
                    Exploring Fields, Properties, Constructors, Methods and Events
                    To get an enumerable array of members arranged by the
                    role they play in the context of a class you can call the
                    respective function. If you want to have all fields, you call
                    “GetFields()”, for properties “GetProperties()” , etc.
                    Exploring attributes, determining implemented interfaces,
                    enumerating nested types, …
                    Likewise, there are methods that give you access to the
                    attributes that are declared on a type and you can also
                    retrieve a list of implemented interfaces and types that are
                    declared within the scope of the current type.
                    Summary: Everything you may ever want to know
                    In short, every structural element that you can express in
                    a language like C# is available through reflection.
18                                Reflection

Section 2: Exploring Metadata




                    Type and Instances
                    Type Safety First! Type checking at runtime
                    In summary, the information available through Reflection
                    allows for more type-safe programming resulting in more
                    solid code. You are now able to do runtime type-checks
                    throughout the .NET platform by actively checking types
                    before you execute an action instead of catching type-
                    cast exceptions (or worse) after you have attempted to
                    execute something on a non-matching type.
                    The C# and Visual Basic.NET languages, like other
                    languages available for the .NET platform, exposes this
                    capability through an extra language keyword.
                    If C# you can test an instance of a class using a “object is
                    class” expression and in VB.NET you can use the more
                    verbose “If TypeOf object Is class Then …” expression.
                    Dynamic Invocation through Reflection
                    Reflection will not only let you walk through types to obtain
                    information about them, but will also let you make calls to
                    class instances, if you use Reflection to implement late
                    bound behavior.
                    Methods can be invoked through Invoke() on the
                    MethodInfo objects returned by GetMethods() and fields
                    can be set with the SetValue() method on the FieldInfo
                    objects returned by GetFields() or on the PropertyInfo
                    returned by GetProperties().
                               Reflection                                19

Section 3: Detail Information




                      Section 3: Detail Information
                      The System.Type class returns a lot of information by
                      using helper classes such as the MemberInfo class. In this
                      section we are taking a closer look at these classes and
                      also how to obtain information on the larger context of a
                      reflected class. You will also learn about Reflection’s
                      unmanaged sibling, the Metadata API, which makes .NET
                      Metadata natively available to unmanaged code.
                      MemberInfo
                      FieldInfo, PropertyInfo
                      ConstructorInfo, MethodInfo
                      The Bigger Picture
                      The Unmanaged Spy: Metadata API
20                                 Reflection

Section 3: Detail Information




                      MemberInfo
                      Base class for all "member" element descriptions
                      The MemberInfo class is the base class of all Reflection
                      information classes for subordinate elements of
                      System.Type.
                      If you enumerate all members of a type using the
                      System.Type.GetMembers() method, an array of
                      MemberInfo objects will be returned that will provide you
                      with basic information about every subordinate element
                      and you can indeed use Reflection itself to test whether a
                      given MemberInfo is of type MethodInfo and do a safe
                      type-cast to explore the specific capabilities.
                      Provides member kind, name and declaring class
                      The MemberInfo base class provides information about
                      the element’s name, its “kind” (that is whether it is indeed
                      a method, field or on of the other kinds) and which its
                      declaring class is.
                               Reflection                                   21

Section 3: Detail Information




                      FieldInfo, PropertyInfo
                      FieldInfo
                      The FieldInfo class contains the member information for a
                      certain field of a class (or structure) including its name and
                      data type and attributes that have been declared on the
                      field inside the structure of class.
                      You will also be able to find out whether the field is an
                      instance field or class field (static) and determine its
                      protection level.
                      Lastly, you can also manipulate a field’s value through
                      Reflection, which is essential for tasks like interception in
                      .NET Remoting.
                      PropertyInfo
                      The PropertyInfo provides you with detail information
                      about a certain property. In addition to the information that
                      is available for fields as discussed above, it also contains
                      the method information for the associated “set” and “get”
                      methods, parameter information if the property is an
                      indexer and you are, of course, able to invoke the “set”
                      and “get” methods directly through the PropertyInfo class.
22                                 Reflection

Section 3: Detail Information




                      MethodInfo, ConstructorInfo
                      MethodInfo
                      The MethodInfo class gives you all details about the
                      signature, attributes and return values of a certain
                      method.
                      All parameter descriptions are accessible in order through
                      the GetParameters() method and low-level details about
                      the embedded IL code are available through a flag-field
                      that can be obtained through a call to the method
                      GetMethodImplementationFlags().
                      The method can also be invoked directly through the
                      MethodInfo class, given an object to execute the call on.
                      ConstructorInfo
                      The ConstructorInfo class, derived from the same base
                      class as MethodInfo (MethodBase), is very similar to the
                      MethodInfo class, but reflects the very specialized
                      initialization methods (constructors) for classes. These
                      should not be called except at construction time and are
                      therefore separated from the methods.
                              Reflection                                   23

Section 3: Detail Information




                      Attributes
                      Custom attributes are the killer-app for Reflection!
                      Custom attributes are the real killer application for
                      Reflection and something that you should really consider
                      looking at very closely.
                      The Reflection features that we highlighted up to here, like
                      all the detailed member information are certainly useful for
                      implementing late-bound applications and for creating
                      more solid code, but attributes indeed enable a whole new
                      development paradigm: attribute-driven programming.
                      Attributes enable declarative behavior
                      Attributes are special elements (classes) in the .NET
                      Framework that allow you to augment any structural
                      element of .NET classes and structures with auxiliary
                      information that is not immediately part of the class’s
                      runtime behavior but serves to provide additional
                      information that is either being evaluated by the runtime
                      and the .NET Framework or your own frameworks.
                      An example for this is the [serializable] attribute, which
                      tells the Serialization framework that it is allowed to
                      serialize a class’s state as-is and using the class
                      Metadata for Remoting or persistent storage. If the
                      attribute is not present, the class implementer essentially
                      denies that permission and either provides an own
                      implementation for serialization through the ISerializable
                      interface or does not permit serialization and remote
                      marshaling at all.
                      As such, simple attributes will only be instantiated if they
                      are explored via Reflection. They are indeed specifically
                      created for this purpose.
24                Reflection

     Attributes allow data augmentation
     Another possible use is the augmentation of data
     elements with additional hints. The shown example
     assumes a (imaginary) persistency framework that uses
     attributes as hints to match class fields to database
     columns. This is the type of information that had
     previously been expressed using macro-driven “maps”,
     which associate members with numbers or text
     expressions in frameworks like the ATL or MFC class
     libraries. With attributes, all this information can now be
     placed where it belongs: At the field declaration itself.
                              Reflection                                   25

Section 3: Detail Information




                      The Bigger picture
                      Types know their Module, Modules know their types
                      Another strong point of the Metadata is that it allows
                      navigating the entire context of a type. A module, reflected
                      by the System.Reflection.Module class, knows all of the
                      types it defines and implements and each types knows its
                      implementing module.
                      Modules know their Assembly and vice versa
                      Likewise, all modules know and make their container
                      assembly accessible and the assembly can list all
                      modules it contains.
                      Code can browse and search its entire context
                      Finally, the Application Domain (AppDomain) class of the
                      “current” application knows all loaded assemblies, so that
                      you have a full information model about an application’s
                      Metadata at any time and from wherever you need it.
26                                 Reflection

Section 3: Detail Information




                      The Unmanaged Spy: Metadata API
                      Unmanaged (COM) Version of Reflection
                      While the Reflection API is accessible only from managed
                      code, tool vendors that want to produce managed code
                      applications from their IDEs or applications that want to
                      interact with managed code may indeed be largely
                      implemented in COM, like the initial release of Microsoft
                      VisualStudio.NET.
                      For these scenario, the .NET Framework provides an
                      alternate implementation of the full functionality of the
                      managed Reflection API as a COM version, which allows
                      you to explore then content and full type information of
                      managed code assemblies from within COM based
                      applications.
                      Used by VisualStudio.NET and Compilers
                      VisualStudio.NET and the .NET compilers, which are
                      mostly unmanaged code in their initial releases (one
                      reason is that bootstrapping the entire environment in one
                      step would be just too difficult in terms of complexity –
                      even for Microsoft) use the COM based version of
                      Reflection to reflect on and emit managed code.
                      Full Access to all Reflection Information for Tools
                      The COM “Metadata API” is in no way a second-class
                      implementation, but has to be seen as a side-by-side
                      sibling to the managed Reflection API.
                      Fully documented in the "Tool Developer's Guide"
                      The complete reference documentation for the “Metadata
                      API” is located in the “Tool Developer’s Guide “portion of
        Reflection                                27

the Framework SDK and is automatically installed with the
kit.
Buddy: Assembly Metadata API
The Metadata API’s “buddy” is the Assembly Metadata
API, which is also documented in the Tools section and
provides navigable access to the Assembly manifest and
allows you to produce such manifests from code.
28                                Reflection

Section 4: Building Types at Runtime




                    Section 4: Building Types at Runtime
                    In this section we are going to cover “the other side” of
                    Reflection, the “Emit” namespace. The informational and
                    navigational capabilities of reflection are already
                    fascinating, but the “Emit” namespace and its classes take
                    this even a step further by enabling you to create .NET
                    applications from within .NET programmatically and
                    without having to go through the complexity of writing
                    binary formats yourself. With this, System.Reflection.Emit
                    is in fact democratizing automatic code generation and
                    lets developers wanting to create code or Metadata from
                    within their applications focus on just that and not on
                    details of the operating system’s loaders.
                    Introducing System.Reflection.Emit
                    Why? Some scenarios …
                    Dynamic Modules and Assemblies
                    Creating Types and Classes
                    Writing IL
                            Reflection                                  29

Section 4: Building Types at Runtime




                    Introducing System.Reflection.Emit
                    Full representation of physical structure
                    The classes in the System.Reflection.Emit namespace
                    reflect the entire physical and logical structure of an
                    assembly and its embedded modules and types.
                    Allows building modules and assemblies at runtime
                    With this, you can create full functional assemblies and
                    modules from within .NET managed code applications (or
                    through the equivalent functionality in the COM Metadata
                    API) at runtime.
                    This allows you to create transient assemblies that reside
                    only in memory for as long as the application is active and
                    to create assemblies that you can persist into files and
                    which can later be used just like any other assembly.
                    Create classes, types and emit IL
                    Inside any assembly’s modules you can create classes,
                    types and emit code expressed in the Microsoft
                    Intermediate Language (IL) for which you can find the full
                    documentation and specifications in the Tool Developer
                    Section of the Framework SDK.
                    Used by .NET compilers to build .NET apps
                    The .NET compilers and runtime components to generate
                    .NET code use the “Emit” part of Reflection. Managed
                    code uses the managed System.Reflection.Emit portion
                    and unmanaged code uses the unmanaged COM API.
30                               Reflection

Section 4: Building Types at Runtime




                    Why? Some Scenarios…
                    So why would you want to generate code
                    programmatically instead of writing C# (or any other
                    language) code and compile it by “traditional” means? The
                    list of scenarios is indeed endless and only limited by your
                    imagination. The following is really just a very short
                    collection of ideas what you could do:
                    Build classes dynamically from script-like code
                    You can use Reflection to create classes dynamically from
                    script-like code. In .NET, the Regular Expression
                    compilers is an actual example of a not-really-a-complete-
                    programming-language programming language that scans
                    and parses input text data and emits managed code
                    directly from the parse tree via Reflection. If your
                    application exposes user-definable formulas or scripting
                    like features, you can use Reflection.Emit to turn these
                    scripts into actual IL code and consequentially into
                    machine code at execution time.
                    Generate code from visual development tools
                    If you use CASE-like tools that express class framework
                    skeletons or even more in-depth specifications in, for
                    instance, UML, you can write code generators that emit
                    the full Metadata for the base classes that business-logic
                    application developers must derive from to implement the
                    logic using your own code-generators that read the UML
                    (or XMI) model and produce the code via Reflection.Emit.
                    Create dynamic wrappers for existing code
                    You may also want to create dynamic wrappers for
                    existing, unmanaged code. A tool that scans C header
                    files or a COBOL copy-section and produces a managed
        Reflection                                31

code assembly that uses P/Invoke to interface with such
existing code-bases could, for instance, produce such
dynamic wrappers that let you leverage existing code-
bases natively.
Transfer code-chunks to remote machines
Reflection.Emit can also be used in conjunction with
Remoting to transfer and regenerate code on remote
machines to execute tasks there. Possible scenarios for
this include distributed numeric processing mirroring the
SETI@home project where the processing code could be
sent along with the data payload and emitted and run at
the destination.
The .NET security model’s cascaded sand-boxing that
let’s you control the permissions for any code that are
calling prevents malicious use of these features.
32                                Reflection

Section 4: Building Types at Runtime




                    Building Assemblies
                    System.Reflection.Emit.AssemblyBuilder
                    The AssemblyBuilder class is at the root of every “Emit”
                    process in that it allows to create new assemblies, which
                    are required to host modules and their classes and
                    associated code.
                    Dynamically create new assemblies
                    The AssemblyBuilder will enable you to create the full
                    manifest for an assembly, associate new modules and
                    resources and specify attributes on the assembly like
                    requested security permissions that apply when the
                    assembly is loaded into an application domain.
                    Can be persisted as files or held in memory, act and behave like
                    any other assembly
                    The AssemblyBuilder state may be saved into a file or just
                    held in memory. If the state is saved, a full features
                    Assembly file with all its subordinate modules is written to
                    the requested location that is in no way different than the
                    files produced by, for instance, the Visual C# compiler on
                    disk or at runtime.
                            Reflection                                 33

Section 4: Building Types at Runtime




                    Building Modules
                    System.Reflection.Emit.ModuleBuilder
                    The ModuleBuilder allows for the complete programmatic
                    definition of a module, which is .NET’s concept of a code-
                    container.
                    Modules contain types, classes and code
                    Modules contain types, classes and code for one or
                    multiple namespaces including their intermediate
                    language code. All of them can be built with the
                    TypeBuilder, MethodBuilder, EnumBuilder classes and
                    their siblings, which can all be created and accessed via
                    the ModuleBuilder class.
                    Allows creating fully functional modules with code
                    The ModuleBuilder allows you to define complete,
                    dynamic modules with all features. Not only can they
                    contain type and class declarations and class
                    implementations but you can also add advanced
                    information that can be used for diagnostic purposes.
                    Can associate source code
                    You can, for instance, associate references to source
                    code documents that were used to produce the output.
                    Emit debug symbols
                    Likewise, you can also emit full symbolic debug
                    information and actually enable .NET debuggers to debug
                    your applications although the code was generated based
                    on your own custom language.
34               Reflection

     Acts like any module created by any .NET compiler
     In the end, the Reflection.Emit produced modules can act
     exactly like any other module in terms of functionality.
                            Reflection                                 35

Section 4: Building Types at Runtime




                    Writing IL
                    Emit accepts IL (Intermediate Language) code
                    The MethodBuilder exposes the method “GetILGenerator”
                    which returns an instance of the ILGenerator classes that
                    eases emitting IL code. The IL code is automatically
                    associates with the method the generator was requested
                    for.
                    Same code as emitted by C#, VB.NET, Eiffel#
                    Since all of the .NET compilers (with a partial exception
                    being C++) produce IL as well, the output from this can be
                    exactly the same as from any of these languages.
                    IL is optimized and translated into machine code
                    The IL is then optimized fro the target machine when it is
                    translated into machine code by one of .NET’s JIT
                    compilers.
                    Reflection.Emit puts you "on-par"
                    Essentially, Reflection.Emit can put you on par with all
                    other development tools out there in that it makes code-
                    generation more accessible, allows you to use the same
                    optimizing back-ends as any other .NET compiler. In .NET
                    programming languages are very smart and syntax aware
                    scanners and parsers that can translate the expressions
                    into terms of the IL.
                    For more info see System.CodeDOM
                    For more information on compiler support you should also
                    take a look at the System.CodeDOM namespace.
36                                  Reflection

Section 5: Putting it Together




                      Section 5: Putting It Together
                      In this last section, we want to take a look at two
                      examples for how Reflection is used within
                      VisualStudio.NET and ASP.NET
                      VisualStudio.NET and Reflection
                      What ASP.NET really does with a page
                              Reflection                                  37

Section 5: Putting it Together




                      VisualStudio.NET and Reflection
                      VisualStudio.NET is certainly the busiest user of
                      Reflection to-date. By looking at the information available
                      in the VisualStudio environment once a project has been
                      loaded, it can easily be derived that VisualStuido.NET
                      obtains a major portion of the information presented from
                      all sorts of assemblies by ways of Reflection.
                      This becomes indeed most obvious in the localized, non-
                      English versions of VisualStudio.NET, since a large
                      portion of the information indeed remains to be expressed
                      in English, because it is pulled from Metadata.
                      The Properties window for components or controls shown
                      in the .NET designers will show browsable properties of
                      .NET components based on attribute settings that it finds
                      via Reflection. The component Metadata will also drive the
                      way the designer windows that are hidden behind the
                      “triple dot” (…) buttons are being launched and
                      associated.
                      The Toolbox window will know what can be displayed in
                      the same way.
38                                 Reflection

Section 5: Putting it Together




                      What ASP.NET does with a Page
                      ASP.NET is also heavily relying on Reflection. The
                      process for creating the ASP.NET assemblies that are
                      executed at runtime can be quickly explained as follows:
                      First the ASP.NET runtime will check whether a requested
                      file does actually exist. The file to be checked for is the
                      actual ASPX text file.
                      Second it will check whether a matching compiled
                      assembly exists that has the same timestamp as the text
                      file.
                      If this is not the case, the ASP.NET compiler will compile
                      the file into a Page class (expressed in C# or the page
                      language) and explores the code-behind assembly via
                      Reflection to be able to match up the page expressions
                      against the code-behind class. In a second step, it invokes
                      the page language compiler to translate the code-
                      generated Page into an assembly.
                      The third step is to execute the Page class’ handling code
                      and return the result to the client.
                  Reflection                                   39

Summary




          Summary
          Reflection = System.Type + GetType()
          At the heart of Reflection are the method GetType() that is
          available on each and every object in .NET and the
          System.Type class that it returns. If you could only
          remember a single thing about Reflection, this should be
          it.
          Explore Type Information for everything at Runtime
          The System.Type class and the additional classes in the
          System.Reflection namespace that accessible through it
          let you explore every structural element of .Net
          applications at runtime without extra effort at development
          or compile time.
          Enables Attribute-driven programming
          Reflection also enables the powerful Attribute-driven
          programming model that lets you add declarative behavior
          to code.
          Use Emit Classes to Produce .NET Assemblies
          You can use the System.Reflection.Emit namespace
          classes to create .NET Assemblies in much the same way
          as the .NET toolsets do it.
          Bottom line: Fully Self-Contained Structural Model
          To sum it all up: With Reflection, .NET provides and
          contains an entirely self-describing and self-contained
          structural model that does not require any external tools to
          create .NET compliant components.

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:0
posted:12/3/2013
language:Unknown
pages:39
doc5671 doc5671
About doc567@yeah.net