CSC/ECE 517 Fall 2009/wiki2 5 jn

From Expertiza_Wiki
Revision as of 18:09, 9 October 2009 by InteliSavant (talk | contribs)
Jump to navigation Jump to search

Reflection APIs (TOC)


Introduction

What is Reflection?

Reflection in programming is a technique in which programs are able to dynamically view and alter their own structure and flow. For example, in reflection one could determine method/variable/class names, add or delete method/variables, alter code to current methods, or simply alter values in variables. Reflection is a subset of MetaProgramming which relies heavily on the use of meta-information. Meta-Information is used to keep track of the program structure such as names of available methods,variables and classes but also is what really makes reflection possible. In theory there are nearly no bounds to reflection as it directly modifies the binary of the program. The current limitations of this process are related to the APIs avaliable for specific languages. Majority of object-oriented languages have the functionality built in and some like C++ require external libraries to achieve even the basic functionality of Reflection.


What languages are Supported?

Due to the complexity required to support this majority of the languages that support this feature tend to be object oriented. Some examples of supported languages are Java, Ruby, C#, Perl, PHP, JavaScript, Python, and ActionScript. In this page we will cover a select few of the languages above and what native API support is avaliable for each of the languages.


Terminology

  • Reflection
  • MetaProgramming
  • MetaData
  • Binding
  • Instance
  • Scope

Available Reflection APIs

Reflection in C#

Reflection in C# is included in the .NET framework provided by microsoft. The methods and classes usable for reflection are access directly from the System.Reflection namespace and support any class type avaliable under the .NET framework. The basis of reflection in C# is powered by the Type class which is the way metadata is accessed. This type object gives information about all avaliable methods, variables, constructors, and more from a given class.


Reflection in C# is not as dynamic as most other languages in the fact that it doesn't easily support the alteration of class variables, methods, and attributes. As shown above the reflection implementation in C# is more for data collection and anaysis for object types. One of the best applications for Reflection in C# is the flexibility to dyniamically load assembly code at runtime, ascertain information about the methods, variables and constructors, and then invoke code from the assembly directly. This type of usage makes examples especially hard to include in a short diescription as this. For this reason the examples have been simplified and is displayed below.



Example

public class Counter
{
     // Private Variable
     private int ctr;
     // Constructor
     public Counter(int temp)
     {
          ctr = temp;
     }
     // Increment
     public int Inc(int temp)
     {
          return ctr+=temp;
     }
     // Decrement
     public int Dec(int temp)
     {
          return ctr-=temp;
     }
}

Suppose we have the basic class as listed above. There is only one constructor, one private instance variable, and two functions which increment or decrement the instance variable by a certain amount. We could easily begin obtaining information about this class by performing the code below.

Counter myCtr = new Counter(1000);
Type tempType = myCtr.GetType();

From the instance of myCtr we were able to use the GetType method to instantiate and parse meta-information about the Counter class. Keep in mind that this class could have been invoked at compile time and that we may have no previous information about it. We could then dynamically determine what constructors and methods were avaliable by performing the following actions.

ConstructorInfo [] c_info = tempType.GetConstructors();
MethodInfo [] m_info = tempType.GetMethods();

From these two lines of code we now have an array of infmoration for both the avaliable methods and the avaliable constructors. We can use the information in these two types to dynamically incoroporate the class into the system at runtime.



Conclusion

The included reflection API in the C# language creates a way for programmers to dynamically retrieve information from external assembly code. They can then proceed to use that information to access the types avaliable from the assembly. While this is a difficult concept to grasp it does have its usages. In the System.Reflection.Emit namespace there is a way to dynamically create types. This form of reflection is typically used by script engines and compilers as they import external types to be used in the current binaries.


Reflection in Java

Reflection in Ruby

The nature of Ruby as an object-oriented language gives great support for Reflection. The big advantage to ruby is it gives us complete flexibility and control with reflection. Most usages of reflection is only to obtain information and create new types dynamically but not modify current ones. With Ruby's reflection api we have the ability to add or remove almost anything, whether that's a method, a class, or even class variables. Please note that this flexibiliy can also lead to a programs downfall as with any reflection API. Too much alteration of the source code can cause many unknown bugs.


The current support for reflection in ruby is built into the language and is accessable through certain fuctions within the standard Ruby API. The methods most commonly used for reflection in Ruby along with some basic examples of their usage are shown below.



Eval Method


The eval method is defined in the Kernel Module of Ruby and is used to evaluate literals encompased in strings. This may not seem useful but the eval method also work in the scope of bindings which represent the scope of execution at a particular place in the code. This allows programmers to view any variables in any scope for any instance. An example of eval's usage is shown below.

Example
    class Test
         def initialize(var)
              @myvar = var
         end 
         def getBinding
              return binding()
         end
    end
    test1 = Test.new("12+5")
    #We can determine what test1's instance of myvar is and evaluate it without an accessor method
    eval("@myvar", test1.getBinding)   #=>  17

I this example we can see that by acquiring the binding at some scope in the program we can use it to get inside the context of any object instance and determine the value of any instance variables.



Instance Eval Method


The instance_eval method is defined in the Object class and works within the instance of any class. This method performs much of the same operations as the eval method but works in the scope of an object without requiring the binding statement as above. In fact we can accomplish the same example as above with the code shown below.

Example
    class Test
         def initialize(var)
              @myvar = var
         end 
    end
    test1 = Test.new("12+5")
    #We can determine what test1's instance of myvar is and evaluate it without an accessor method
    test1.instance_eval { @myvar }   #=>  17

Again this code performs exactly the same thing as the prior example above. The result is 17 which is the evaluation of the string literal as a command.



Class Eval Method


The class_eval method is defined in the Module class and works within the instance of any class. This method can be used to work within the context of any object whether that is assigning or accessing variables, declaring instance methods, or even re-defining inherited methods. The method takes actions either via string literal or a block of code. This method is one of the strongest and most versatile methods in the Ruby Reflection API since it can access any private methods of any objects and its parents, this giving you full control over control.

Example 1
    class Test
         def initialize(var)
              @myvar = var
         end 
    end
    test1 = Test.new("12+5")
    #We can determine what test1's instance of myvar by creating an accessor method for this instance.
    test1.class_eval{ def getVar; @myvar; end }
    eval(test1.getVar)   #=>  17
    #Or by simply accessing the local variable as below.
    eval(test1.class_eval{@myvar})    #=> 17

This example shows the versatility of the class_eval method to work on any class instance. It performs many of the operations that the previous methods have performed but with the added advantage of assigning instance methods.

Example 2
    class Test
         def initialize(var)
              @myvar = var
         end 
      private:
         def increment
              @myvar += 1
         end
    end
    test1 = Test.new(17)
    #We can directly use class_eval to call private methods within a class as well.
    test1.class_eval{ increment() }   #=> 18

This example shows that class_eval has even more flexibility to call private functions of a class from outside of the class scope.

Example 3
    class Test
         def initialize(var)
              @myvar = var
         end 
    end
    test1 = Test.new(17)
    # We can directly use class_eval to add variables to the instance of the class
    test1.class_eval{ instance_variable_set :@myvar2 , 25 }   
    test1.class_eval{ @myvar2 } #=> 25
    # Or We can remove variables from an instance of the class
    test1.class_eval{ remove_instance_variable :@myvar2 }
    test1.class_eval{ @myvar2 } #=> nil

This example shows that class_eval is capable of defining and removing instance variables from the instance of a class.



Define Method Method


The define_method method is defined in the Module class and works within the instance of any class. This method can be used to work within the context of any object to declare methods directly. This method can be accomplished by using the class_eval method but is also a bit more flexible in it's notation. An example of the use of this function is shown below.

Example
    class Test
         def initialize(var)
              @secret = n
         end 
    end
    test1 = Test.new("This is my String!")
    #We can use define_method to create a instance method for this class with multiple parameters.
    test1.class_eval{ define_method(:getSubString){|start, end| @secret[start,end]} }
    test1.getSubString(5,9)   #=> "is my"

This example shows how to use define_method to create an instance method with multiple parameters by the common block notation. Please not that we did have to use class_eval still to access the define_method. This was due to the fact that define_method is a private method within the Module class.



Conclusion


The ruby language provides great support for reflection due to the nature of its design. By using the class_eval method by itself one could completely encompass majority of the required reflection programming. The other functions do provide some other basic support not specifically granted to the class_eval function. Specifically the eval function in combination with bindings. The use of bindings allow the program to save the context of scope at some particular moment in the program and access it later. With these functions ruby makes reflection simple.


Reflection in PHP

Reflection in PERL

Conclusions

Links

[1] Reflection Wikipedia

[2] Reflection in C# - CoderSource.net

[3] MSDN Visual C# - Reflection Programmers Guide

[4] Ruby Reflection

[5] A Ruby Metaprogramming Introduction

[6] Ruby Programmging Language - Reflection and Metaprogramming