WHAT'S NEW?
Loading...

Day 8 Programming in C# 70-483

Index


  • Introduction
  • Manage attributes
  • Access your code at runtime
  • Generate code at runtime
  • References

Introduction

This post is part of a series of post to help you prepare the MCSD certification, particularly the certification exam 70-483, based on the book:


You will find all the code available in the following GitHub repository. Lets talk a little bit about threads and how they work using a .Net development environment.

Manage attributes


In a .Net application you have mainly code and data, but there's also something called metadata which could be defined as some information about the data in your app. There are types of metadata which contain info regarding the types, code, assembly and other elements in your applications.

Reflection is process of retrieving this metadata at runtime.

Attributes are handy to provide information and decorate all kind of types: types, assemblies, methods. Use [Serializable] attribute just above a class definition to tell the compiler this class and all its types can be serialized. It's defined in System.SerializableAttribute (by convention use the "Attribute" suffix to import but not to invoke.)

Attributes can have parameters like [Conditional("CONDITION1"), Conditional("COND2")] meaning a call to a particular method should be ignored by the compiler unless a condition is satisfied. 

Check the AssemblyInfo.cs class to get a hint of how to specify a target when defining an attribute:


Now is the time to read these attributes. The System.Attribute class contains some static methods that can be used with Reflection. Let's start with an example of reading the Serializable attribute in a class and take a decision based on that. Then, by using the ConditionalAttitribute we can run or not one or more methods as shown here:


You can define your own attribute by inheriting from System.Attribute. You can also define the possible targets your custom attributes can point to (classes, methods, etc.). Besides, by using the keyword "AllowMultiple" you define that you attribute can be instantiated multiple times by the same type (means you can write the same attribute multiple times just before the type definition probably because you need to pass different parameter values). Bear in mind, all attribute properties have to be read-write.



In the previous example we've decorated our Developer class with a couple of categories: Human and Person, so we can get that information during runtime by using reflection.

Access your code at runtime

In the previous example we've decorated our Developer class with a couple of categories: Human and Person, so we can get that information during runtime by using reflection. Unfortunately, reading this data by using Reflection is an expensive operation.

Typical example of when use reflection is when playing with plugins. Imagine you have an app with a plugin folder where you can drop anything you want. Then, you need your application smart enough to differ between what is and what's not a plugin.

You can start by creating your own IPlugin interface so you can "force" developers to implement it in order to be used by our main app. Then, when reading the assemblies from the plugin folder with the Assembly.Load("assemblyname"); command you'll end up building a LINQ query with something like this:

There are more functions you can use from Reflection. You can inspect properties or even methods. Imagine you need to iterate over a type and get all the integer defined there. You can use BindingFlags enumeration to control how reflection performs searches for members. For methods, you can trigger a method by using the Invoke function.

Generate code at runtime


But not everything is define attributes and read them, you can even generate your own code at runtime. You can use the CodeDOM framework to create your own source files or a binary assembly that can be executed. This library is placed in the System.CodeDom namespace. To be used you first need to define a container called CodeCompileUnit which contains namespaces, classes, methods and so. Once all is defined, and the compilation unit is complete, you need to call the CSharpCodeProvider to build your source file.

There are two more subjects to mention here: lambda expressions and expression trees. The first was introduced in C# v3 and is closely related with Function and Action delegate classes. You can use Action in case you don't need to return any value and Func when you do. 

Expression trees are representations of code, a description, defined in a tree-way. Commonly used with LINQ, a expression tree describes the query (System.Linq.Expressions).



In the previous example the expression is built with a call to Console.Write and Console.WriteLine, then, the expression is compiled to an Action because it doesn't return anything.

0 comments:

Post a Comment