Component Programming with C# and .NET Prof. Dr. Andreas Polze Operating Systems and Middleware Chair Hasso-Plattner-Institute at University Potsdam Prof.-Dr.-Helmert-Str. 2-3 14482 Potsdam, Germany
[email protected] andreas.polze.de, www.dcl.hpi.uni-potsdam.de AP 02/03
Overview • The Notion of Component-Oriented Programming – Objects vs. Components – Concepts of reuse, deployment, (graphical) builder tools
• Component Systems – NeXTSTEP Interface Builder, Java Beans, Component Object Model (COM)
• Component Programming with .NET • Aspects: Problems with Component Frameworks – Non-functional component properties – Aspect-oriented programming
• How C# and .NET change the scene – Dynamic Re-Configuration in a .NET component framework – Reflection and attributed-based programming – our aspect weaver
• Conclusions AP 02/03
1
Why Components? „Software components are binary units of independent production, acquisition, and deployment that interact to form a functioning system“ (Szyperski 1997) The rationale behind component software: • Largely pushed by desktop – and Internet-based solutions. • Complex technology to master – viable, component-based solutions will only evolve if benefits are clear. • Benefits of traditional enterprise computing depend on enterprises willing to evolve substantially. AP 02/03
Terms and Concepts Components: • are units of independent deployment; • are units of third-party composition; • have no persistent state. Implications: • A Component needs to be well-separated from its environment and from other components. • A component encapsulates its constituent features. • Components are never partially deployed. AP 02/03
2
Observations on Components • Components need to come with clear specifications of what they provides and what they require. – Functional vs. non-functional properties – Well-defined interfaces and platform assumptions are essential. – Minimize hard-wired dependencies in favor of externally configurable providers.
• Components cannot be distinguished from copies of themselves. • In any given process, there will be at most one copy of a particular component. – So, while it is useful to ask whether a particular component is available or not, it isn’t useful to ask about the number of copies of that component.
• Many currently available components are heavyweights. – Database server, operating system services AP 02/03
Terms and Concepts (contd.) Objects: • are units of instantiation (Each object has a unique identity); • have state that can be persistent; • encapsulate their state and behavior. Implications: • Objects cannot be partially instantiated. • Since an object has individual state, it also needs a unique identity to identify the object, despite state changes, for its lifetime. • Nothing but an object‘s abstract identity remains stable over time.
AP 02/03
3
Observations on Objects • Objects need a construction plan that describes the new object’s state space, initial state, and behavior before the object can exist. – Such a plan may be explicitly available and is then called a class. – Alternatively, it may be implicitly available in the form of an object that already exists, that is close to the object to be created, and can be cloned. – A preexisting object might be called a prototype object.
• The newly instantiated object needs to be set to an initial state. – The initial state needs to be a valid state of the constructed object, but it may also depend on parameters specified by the client asking for the new object. – The code that is required to control object creation and initialization could be a static procedure, usually called a constructor. – Alternatively, it can be an object of its own, usually called an object factory, or factory for short. AP 02/03
Components and Objects illustrated Entry point (CoGetClassObject())
Component (unit of deployment)
Interface (IUnknown)
Class Factory A
Class Factory B
A object A object
B object
Components are rather on the level of classes than of objects AP 02/03
4
Interfaces • A component’s interfaces define its access points. – These points let clients access the component’s services. – Components may have multiple interfaces. – Each access point may provide a different service.
• Interface specifications have contractual nature. – Component and clients are developed in mutual ignorance. – The standardized contract forms ground for successful interaction.
• Economy of scale: – interfaces should be simple, extensible and fulfill a market need.
• Common media to advertise interfaces is required – Unique naming scheme (e.g., ISBN numbers). – Component identifier is not required to carry any meaning. AP 02/03
Explicit Context Dependencies • Besides specifying provided interfaces, components are also required to specify their needs. – What does the deployment environment need to provide, so that the components can function (so-called context dependencies). – For example, a mail-merge component would specify that it needs a file system interface.
• Problems with today’s components: – The list of required interfaces is not normally available. – Emphasis is usually just on provided interfaces.
• Non-functional component properties are not addressed – CPU/memory usage, timing behavior, fault-tolerance properties. AP 02/03
5
The Ultimate Difference • Components capture the static nature of a software fragment. • Objects capture its dynamic nature. – Simply treating everything as dynamic can eliminate this distinction.
• Good software engineering practices strengthen the static description of systems as much as possible. – Dynamics can always be superimposed where needed. – Meta-programming and just-in-time compilation simplify this soft treatment of the boundary between static and dynamic.
AP 02/03
I
Components at Work
Setting the stage: NeXTSTEP and its tools
AP 02/03
6
AP 02/03
Déjà vu
AP 02/03
7
NeXTSTEP InterfaceBuilder • Component model based on Objective-C – Class == object – Runtime type info
• Graphical management of events – Revolutionary tool (1991) – Interconnects event sources and sinks graphically
AP 02/03
II
Components at Work
The JavaBeans component model
AP 02/03
8
JavaBeans Basics • Any object that conforms to certain rules can be a bean. – No Bean-superclass – Java Beans have to implement the interface „Serializable“
• Many beans are AWT components – AWT = Abstract Windowing Toolkit – Invisible beans may be useful
• A bean is characterized by properties, events, and methods it exports. • A bean communicates by generating events. – Event model is based on java.util.EventObject and java.util.EventListener interfaces AP 02/03
JavaBeans - conventions • Class name – No restrictions on the class name of a bean
• Superclass – A bean can extend any other class – Often AWT or Swing components
• Instantiation – Must provide no-parameter constructor or – File containing serialized instance of prototype bean (.ser-ext.)
• Bean name – Name of the class that implements it or name of the file that holds serialized instance of the bean
AP 02/03
9
Methods • Public methods describe the Bean’s behavior. – Excluding methods that get/set property values – Excluding methods that register/remove event listeners
• Public methods are exposed by the builder tool. • The methods are used by the builder tool or the user to construct connections between Beans.
AP 02/03
Properties A bean defines a property p of type T if it has an accessor method adhering to the following naming pattern: • Getter: – public T getP()
• Boolean getter: – public boolean isP()
• Setter: – public void setP( T )
• Exceptions:
Special cases: • Indexed properties • Bound properties • Constrained properties • Property editors • Customizers
– Property accessor methods can throw any type of checked or unchecked exceptions AP 02/03
10
Structuring and Packaging • JavaBeans are delivered by means of a JAR file. • A JAR that contains a Bean must include: – a Manifest declaring the Beans it contains, – be it a class or a persistent representation of a prototype of the Bean.
• In the absence of additional information: – a builder tool that uses JavaBeans components from a series of JAR files will need to include all files in these JARs
• Express Inter-Bean dependencies: – Design-Time-Only and Depends-On tags. (JavaBeans 1.01)
Demo
III Skip
AP 02/03
Components at Work
The Component Object Model (COM+)
AP 02/03
11
COM – The idea COM is based on three fundamental ideas • Clients program in terms of interfaces, not classes (classic COM) • Implementation code is not statically linked, but rather loaded on-demand at runtime (classic COM) • Object implementers declare their runtime requirements and the system ensures that these requirements are met (MTS & COM+)
AP 02/03
Definitions • •
Two key terms have been defined so far A COM Interface is a collection of abstract operations one can perform on an object – – –
•
A COM Object is a collection of vptrs in memory that follow the COM identity laws – –
•
Must extend IUnknown directly or indirectly Identified by a UUID (IID) Platform-specific vptr/vtable layout
Must implement at least one COM interface QueryInterface ties vptrs together into cohesive object
A single component can support multiple COM classes –
Which are used to construct COM objects AP 02/03
12
The COM Runtime Environment
Foo.dll
Bar.exe
Bar.exe
OLE32.DLL
OLE32.DLL
OLE32.DLL
SVCHOST.EXE SVCHOST.EXE
SVCHOST.EXE SVCHOST.EXE AP 02/03
COM class loading and activation Client.exe
2
rpp rpms
mobile.dll
3 4
pcf 1
1 Client calls CoGetClassObject 2 Client calls CreateInstance on Class Object 3 Client calls QueryInterface on Class Instance COM & .NET
4 Client calls Release on Class Object
AP 02/03
13
IV
Components in C# and .NET
AP 02/03
The Evolution of Components (Microsoft-style)
Fine-grain Integration
CLR
Course-grain Integration
XML HTTP
Win32 C++ VB6 COM DCOM
AP 02/03
14
Type fragmentation under COM
Lib1
Lib2
COM Type System
Lib3
Internal Type System
AP 02/03
Pervasive Type in the CLR
Lib1
Lib2
Lib3
CLR Type System
AP 02/03
15
Type segregation under XML
Lib1
Lib2
XML Type System
Lib3
Internal Type System
AP 02/03
Object Creation and the Loader Win32
COM
CLR
LoadLibrary
CoCreateInstance
Assembly.Load
GetProcAddress
QueryInterface
GetType
MZ Header
MZ Header
MZ Header
PE Header
PE Header
PE Header
COFF Header
COFF Header
COFF Header
Type Library
CLR Metadata
Executable Machine Code
Executable IL/Machine Code
Executable Machine Code
AP 02/03
16
CLR Architecture Your Managed Code
MSCOREE.DLL "The Runtime"
MSCORLIB.DLL "The Runtime Library"
MZ Header
MZ Header
MZ Header
PE Header
PE Header
PE Header
COFF Header
COFF Header
COFF Header
CLR Metadata
Type Library
CLR Metadata
IL/Machine Code
Machine Code
IL/Machine code
AP 02/03
The CLR Type System T[] Decimal SByte
Array
Byte Int16
String
UInt16 Int32
Object
ValueType
UInt32 Int64
interface T
UInt64
class T
Single Boolean
Delegate
Double Char
delegate T
struct T
Enum
enum T
AP 02/03
17
Metaprogramming and Reflection in .NET Remote method invocation
COM Type Information JVM Type Information
Transparent Proxies and Interception
Directory Type Information
CLR Type Information
Automatic Serialization
Code Generation
DBMS Type Information XML Type Information
Documentation and Analysis
AP 02/03
Pervasive type and GetType Type Patient
typeof(Patient)
this.id.GetType()
Type Int32
typeof(int)
this.age.GetType()
Type Double
typeof(double)
this.dead.GetType()
Type Boolean
typeof(bool)
this.GetType() id age dead
class Patient { int id; double age; bool dead; }
AP 02/03
18
Pervasive type and System.Type typeof(Patient)
Type Patient
GetType()
typeof(int)
Type Int32
GetType() Type Type
typeof(double)
Type Double
GetType()
GetType() typeof(Type)
typeof(bool)
Type Boolean
GetType()
AP 02/03
Component Programming with C# and .NET • • • •
1st Class Component Support Robust and Versionable Creating and using attributes API integration – DLL import – COM support
• Preserve Existing Investments
AP 02/03
19
What defines a component? • What defines a component? – Properties, methods, events – Design-time and runtime information – Integrated help and documentation
• C# has first class support – Not naming patterns, adapters, etc. – Not external files
• Easy to build and consume AP 02/03
Properties • Properties are “smart fields” – Natural syntax, accessors, inlining public class Button: Control { private string caption; public string Caption { get { return caption; } set { caption = value; Repaint(); } } }
Button b = new Button(); b.Caption = "OK"; String s = b.Caption;
AP 02/03
20
Indexers • Indexers are “smart arrays” – Can be overloaded public class ListBox: Control { private string[] items; public string this[int index]{ get { return items[index]; ListBox listBox = new ListBox(); } listBox[0] = "hello"; set { Console.WriteLine(listBox[0]); items[index] = value; Repaint(); } } } AP 02/03
Events • Efficient, type-safe and customizable – Built on delegates
public class MyForm: Form { public MyForm() { Button okButton = new Button(...); okButton.Click += new EventHandler(OkButtonClick); } void OkButtonClick(…) { ShowMessage("You clicked OK"); } }
AP 02/03
21
Design/Runtime Information • Add information to types + methods? – Transaction required for a method? – Mark members for persistence? – Default event hookup?
• Traditional solutions – Lots of custom user code – Naming conventions between classes – External files (e.g. .IDL, .DEF)
• The C# solution - Attributes AP 02/03
Attributes • Appear in square brackets • Attached to code elements [HelpUrl(“http://SomeUrl/Docs/SomeClass”)] class SomeClass { [WebMethod] void GetCustomers() { … } string Test([SomeAttr] string param1) {…} } AP 02/03
22
Attribute Fundamentals • Attributes are classes! Completely generic class HelpUrl : System.Attribute { public HelpUrl(string url) { … } … } [HelpUrl(“http://SomeUrl/APIDocs/SomeClass”)] class SomeClass { … } • Easy to attach to types and members Type type = Type.GetType(“SomeClass”); object[] attributes = type.GetCustomAttributes(); • Attributes can be queried at runtime AP 02/03
Calling Into Existing DLLs • .NET Framework contains attributes to enable calling into existing DLLs • System.Runtime.InteropServices – DLL Name, Entry point, Parameter and Return value marshalling, etc.
• Use these to control calling into your existing DLLs – System functionality is built into Framework
AP 02/03
23
Attributes to specify DLL Imports [DllImport("gdi32.dll")] public static extern int CreatePen(int style, int width, int color); [DllImport("gdi32.dll",CharSet=CharSet.Auto)] public static extern int GetObject( int hObject, int nSize, [In, Out] ref LOGFONT lf);
AP 02/03
COM Support • .NET Framework provides great COM support – TLBIMP imports existing COM classes – TLBEXP exports .NET types
• Most users will have a seamless experience
AP 02/03
24
on-the-fly COM
Obj1
CCW
RCW mscoree.dll
Obj2 ~mscoree.dll
• COM callable wrapper (CCW) • runtime callable wrapper (RCW) AP 02/03
Calling into a COM component • Create .NET assembly from COM component via tlbimp • Client apps may access the newly created assembly using System; using System.Runtime.InteropServices; using CONVERTERLib; class Convert { public static void Main(string [] args) { CFConvert conv = new CFConvert(); ... fahrenheit = conv.CelsiusToFahrenheit( celsius ); Demo
AP 02/03
25
COM Support • Sometimes you need more control – Methods with complicated structures as arguments – Large TLB – only using a few classes
• System.Runtime.InteropServices – COM object identification – Parameter and return value marshalling – HRESULT behavior
AP 02/03
COM Support Example [Guid(“56A868B1-0AD4-11CE-B03A-0020AF0BA770”)] interface IMediaControl { void Run(); void Pause(); void Stop(); … void RenderFile(string strFilename); }
Back to AOP
AP 02/03
26
.NET Programming in Managed C++ CLR operation
C#
Managed C++
Interface declaration
interface IFoo{}
__gc __interface IFoo{}
Class declaration
class Foo{}
__gc class Foo{}
Property declaration int x {get; set;}
__property int get_x(); __property void set_x(int x);
Property impl.
int x { get{ return m_;} set{ m_x = x; }}
__property int get_x() { return m_x; } __property void set_x(int x) { m_x = x; }
Interface impl.
class Foo: IFoo {}
class Foo: public IFoo {} AP 02/03
Managed C++ (contd.) CLR operation
C#
Managed C++
Delegate declaration delegate void call(); __delegate void call(); Indexer declaration
String this[int index] { .... }
[System::Reflection:: DefaultMemberAttribute( S“Item“)] __gc class MyCollection { __property String* get_Item(int index); }
Assembly reference
/r:assembly.dll
#using
Namespace import
using System;
using namespace System;
Namespace ref.
System.Console. WriteLine(„text“);
System::Console:: WriteLine(„text“); AP 02/03
27
Managed C++ (contd.) CLR operation
C#
Object variable
IFoo foo = new Foo();
Managed C++ IFoo * pFoo = new Foo();
Method invocation foo.DoFoo();
pFoo->DoFoo();
Enumeration decl.
enum Foo { bar, qx }
__value enum Foo { bar, qx }
Name clash resolution
void IArtist.Draw() {} void IArtist::Draw() {} void ICowBoy.Draw(){} void ICowBay.Draw() {}
Value type
struct Foo { ... }
Abstract type
abstract class Foo { .. } __abstract class Foo {.. };
Sealed type
sealed class Foo { ... }
__value struct Foo{ ... }; __sealed class Foo { ... }; AP 02/03
Managed C++ (contd.) CLR operation
C#
Managed C++
C-style typecast try { try { IFoo foo = (IFoo)bar; } IFoo* pFoo = catch ( IllegalCastException e){} __try_cast(pBar); } catch ( IllegalCastException* e){} Dynamic type IFoo foo = bar as IFoo; IFoo* pFoo = cast if (foo != null) ... dynamic_cast (pBar); if (pFoo != NULL) ... Type check
if (bar is IFoo) ...
if (dynamic_cast (pBar) != NULL) ... AP 02/03
28
Interludium
spectOriented Programming AP 02/03
Example: a distributed digital library Library
Library
Printer
Class graph Book title: string author: string isbn: int pdf: pdf tiff: tiff
* holds *
*
cooperates
Library
*
* accesses
* User
*
uses
*
Printer AP 02/03
29
the code Book
User
Library
class Book { private String private String private String private PostScript private User
class User { private String name; Library theLibrary; Printer thePrinter;
class Library { Hashtable books; Library(){ books = new Hashtable(100); } public Book getBook(User u, String title) { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) { b.set_borrower(u); return b; } } } return null; } }
title; author; isbn; ps; borrower;
public Book(String t, String a, String i, PostScript p) { title = t; author = a; isbn = i; ps = p; }
public User(String n) { name = n; } public boolean getBook (String title) { Book aBook = theLibrary.getBook(this, title); thePrinter.print(this,aBook); return true; } }
public User get_borrower() {return borrower;} public void set_borrower(User u) {borrower = u;} public PostScript get_ps() { return ps; } }
Printer public class Printer { String status = “Idle”; Vector jobs; public boolean print (User u, Book b) { PostScript ps=get_ps(b); Job newJob = new Job (ps, u.get_name()); return queue(newJob); } boolean queue(Job j) { //... return true; } }
AP 02/03
All is well • Design is natural • Code looks like the design • Good separation of concerns – localized in the design – localized in the code – handled explicitly
AP 02/03
30
Minimizing Network Load Computer A
Computer B
library
library
Computer C printer
book
user title, author, isbn printable format
Computer D
AP 02/03
revised
the code Book class Book { private BookID private PostScript private UserID
id; ps; borrower;
User
Library
class User { private UserID id; Library theLibrary; Printer thePrinter;
interface LibraryInterface extends Remote { public BookID getBook(UserID u, String title) throws RemoteException; public PostScript getBookPS(BookID bid) throws RemoteException; }
public User(String n) { id = new UserID(n); }
public Book(String t, String a, String i, PostScript p) { id = new BookID(t,a,i); ps = p; } public public public public
public boolean getBook (String title) { BookID aBook=null; try{ aBook = theLibrary.getBook(id, title); } catch (RemoteException e) {} try { thePrinter.print(id, aBook); } catch (RemoteException e) {} return true; } public UserID get_uid() { return id; }
UserID get_borrower() {return borrower;} void set_borrower(UserID u) {borrower = u;} PostScript get_ps() { return ps; } BookID get_bid() { return id; }
} class BookID { private String private String private String
title; author; isbn;
public BookID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title;}
} class UserID { private String name; public UserID(String n) { name = n; } public String get_name() { return name; } }
}
Printer interface PrinterInterface extends Remote { public boolean print (UserID u, BookID b) throws RemoteException; } class Printer extends UnicastRemoteObject implements PrinterInterface { String status = “Idle”; Vector jobs; private Library theLibrary; public Printer() throws RemoteException{} public boolean print (UserID u, BookID b) throws RemoteException{ PostScript ps=null; try{ps = theLibrary.getBookPS(b);} catch (RemoteException e) {} Job newJob = new Job (ps, u.get_name()); return queue(newJob); } boolean queue(Job j) { //... return true; }
class Library extends UnicastRemoteObject implements LibraryInterface Hashtable books; Library() throws RemoteException { books = new Hashtable(100); } public BookID getBook(UserID u, String title) throws RemoteException { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) { b.set_borrower(u); return b.get_bid(); } } } return null; } public PostScript getBookPS(BookID bid) throws RemoteException { if (books.containsKey(bid.get_title())) { Book b = (Book)books.get(bid.get_title()); if (b != null) return b.get_ps(); } return null; }
{
}
AP 02/03
}
31
Why? • why did so much code change? • why wasn’t this concern well localized? • why didn’t this “fit” the component structure? because • we are working with “emergent entities”, and • the component concept fundamentally does not provide adequate support for working with emergent entities
AP 02/03
Assume a… library
class Book { private String title; private String author; private String isbn; private PostScript ps; private User borrower; public Book(String t, String a, String i, PostScript p) { title = t; author = a; isbn = i; ps = p; }
public class PrinterImpl { String status = “Idle” Vector jobs;
public User get_borrower() {return borrower;} public void set_borrower(User u) {borrower = u;} public PostScript get_ps() { return ps; }
4 classes
}
class User { private String name; Library theLibrary; Printer the; Printer public User(String n) { name = n; }
}
public boolean getBook (String title) { Book aBook = theLibrary.getBook(this, title); thePrinter.print(this,aBook); return true; }
}
class Book { private BookID id; private PostScript ps; private UserID borrower;
public PrinterImpl() {} pubilc get_status() { return status } public add_job(int j) { jobs.add(j); }
library
public Book(String t, String a, String i, PostScript p) { id = new BookID(t,a,i); ps = p; }
public User(String n) { id = new UserID(n); } public boolean getBook (String title) { BookID aBook=null; try{ aBook = theLibrary.getBook(id, title); } catch (RemoteException e) {} try { thePrinter.print(id, aBook); } catch (RemoteException e) {} return true; } public UserID get_uid() { return id; }
public UserID get_borrower() {return borrower;} public void set_borrower(UserID u) {borrower = u;} public PostScript get_ps() { return ps; } public BookID get_bid() { return id; } }
class Library { Hashtable books; Library(){ books = new Hashtable(100); } public Book getBook(User u, String title) { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) b.set_borrower(u); return b; } } return null; } }
class BookID { private String title; private String author; private String isbn;
“weaver”
public BookID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title;}
printer
book
class User { private UserID id; Library theLibrary; Printer thePrinter;
user }
class UserID { private String name; public UserID(String n) { name = n; } public String get_name() { return name; } }
}
interface PrinterInterface extends Remote { public boolean print (UserID u, BookID b) throws RemoteException; }
interface LibraryInterface extends Remote { public BookID getBook(UserID u, String title) throws RemoteException; public PostScript getBookPS(BookID bid) throws RemoteException; }
public class Printer extends UnicastRemoteObject implements PrinterInterface { private Vector jobs = new Vector(10, 10); private Library theLibrary;
portal Printer { void print(Book book) { book: Book: {direct pages;} }
public Printer() throws RemoteException{} public boolean print (UserID u, BookID b) throws RemoteException{ PostScript ps=null; try{ ps = theLibrary.getBookPS(b); } catch (RemoteException e) {} Job newJob = new Job (ps, u); return queue(newJob); } boolean queue(Job j) { //... return true; }
portal Library { Book find (String title){ return: Book: {copy title, author, isbn;} } }
2 aspects
}
class Library extends UnicastRemoteObject implements LibraryInterface Hashtable books; Library() throws RemoteException { books = new Hashtable(100); } public BookID getBook(UserID u, String title) throws RemoteException { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) b.set_borrower(u); return b.get_bid(); } } return null; } public PostScript getBookPS(BookID bid) throws RemoteException { if (books.containsKey(bid.get_title())) { Book b = (Book)books.get(bid.get_title()); if (b != null) return b.get_ps(); } return null; }
{
}
• a “language processor” that – accepts two kinds of code as input; – produces “woven” output code, or – directly implements the computation
(more at www.parc.xerox.com/csl/projects/aop/) AP 02/03
32
V
Components at Work
Aspect-Oriented Programming with C# and .NET
AP 02/03
C# and the CLR Besides its (functional) interfaces, the specification of a component‘s non-functional properties (RT, FT, Sec.) is essential for predictable component-based systems. • C# integrates component support into the language • C# provides special notion for a component‘s resources • CLR provides a language-independent type system
AP 02/03
33
Problem Statement • Quality-of-Service properties, such as fault-tolerance, timeliness, security should be separated from component implementation – Concentrate on object replication (as basic building block) – Attributes and reflection for integration of aspect-data and component
Object
???
Replicated Objects AP 02/03
Attributes in .NET • • • • • •
Web Services COM Interop Platform Invoke (DLL Interop) Transaction Contexts Permissions Custom XML Persistence
• User-defined attributes to specify non-functional component properties (RT / FT / Security / Config. ) AP 02/03
34
Replication based on Attributes • Specification of a component‘s non-functional properties at namespace CalculatorClass { design time using System; using proxy; • A tool may generate code to automatically create replicated [TolerateCrashFaults(4)] objects public class Calculator { • Component behavior described ... by user-defined attributes public double add (double x, double y) { return x + y; } } } AP 02/03
C# Attribute, A Reliable Calculator
Eiffel# Annotation??
[TolerateCrashFaults(4)] public class Calculator {
Calculator c= new Calculator();
public Calculator(){
c.Op1=3;
Op1=0;
c.Op2=7;
Op2=0;
Console.WriteLine(c.Add());
} public int Op1;
10
10
10
public int Op2; public int Add() { return Op1+Op2;
???
10
} } AP 02/03
35
Behind the scenes... public sealed class Calculator:CalculatorClass.Calculator { private CalculatorClass.Calculator[] _bc; public Calculator(): base() { Reflection _ErrorCount=0; int _Count=1; System.Attribute[] _arAtt = System.Attribute.GetCustomAttributes(GetType()); foreach(System.Attribute _attr in _arAtt) { if(_attr is TolerateCrashFaults) Attribute-based _Count=((TolerateCrashFaults)_attr).Count; programming } /// creation of sufficiently many proxy objects _bc=new CalculatorClass.Calculator[_Count]; AP 02/03
From the consumer‘s perspective namespace CalculatorFront { using System; /// using CalculatorClass; using CalculatorClass; using proxy;
Minimal code changes
public class MainClass { public MainClass() {} public static int Main(string[] args) { Calculator calc = new Calculator(); ... result = calc.add(val1, val2); AP 02/03
36
Towards a Solution First Approach: • Redirect all method calls targeting a particular object using C#‘s concept of delegates – Inheritance relations are not preserved – Applicable for methods only (but not for member variables)
Second Approach: • Generate proxy classes – Static solution, tool support required
AP 02/03
Tool Support Component (Assembly) „aspect weaver“ Attributed/Extended Component client-side modifications
Implementation, extended by aspects AP 02/03
37
LOOM.NET • AOP framework for .NET by Wolfgang Schult (HPI) • Static and dynamic aspect weaver • Combines binary .NET assembly and aspect code to a new application – – – –
Generation of derived proxy classes (reflection) Extension of these proxies with the aspect code Generation of the new application Aspect information is given through ‚templates‘ for namespace, constructor, class, method or field definitions
AP 02/03
Graphical Frontend to LOOM.NET • An aspect is defined as a set of templates for classes, methods, ... • Weaver generates new code and builds the application • Weaving can be restricted to chosen entities (e.g. methods) • Aspects can be parameterized
AP 02/03
38
The Aspect-Weaver Initial idea: the compiler approach • Generate attributed-grammar tree from sources • Integrate aspect-code into the tree – Single language solution; separate tool chain for every additional language required
The .NET approach • Based upon type-info in CLR and reflection • Two roads towards an implementation: – 1. „Reflection API“ as implemented for .NET languages – 2. Unmanaged Metadata-Interfaces Demo
AP 02/03
Migration Aspect: Constructor Template •
Instantiates migration library
•
Takes policy and PMH file name from weaving parameters
• •
Applied on application class constructor Weaver replaces template arguments for every method and generates the new application code
/*[PROTECTION]*/ /*[CLASSNAME]*/(/*[PARAMDECLARATION]*/) : base(/*[PARAMDECLARATION]*/) { mF = (IMigrantLib)new MigrationClientFacility(); mF.Start(this, /*[POLICY_MODULE]*/,/*[PMH_MODULE]*/); } AP 02/03
39
Migration Aspect: Method Template public /*[MODIFIER]*//*[RESULTTYPE]*//*[METHODNAME]*/(/*[PARAMDECLARATION]*/) { if (mF != null) { if (mF.MigrateIfNeededSearchHost()) { try { // Migration finished , leaving this application if (CurrentDomain.FriendlyName.ToString().StartsWith("Migrant Domain")) // was re-migration, closing the env. would kill migration server Thread.CurrentThread.Abort(); else // was first migration, we can kill the application Environment.Exit(0); } catch(ThreadAbortException) {} } else { Console.WriteLine("Migration library call failed."); } } /*[RETVALINIT]*/ /*[RETVALASSIGN]*/base./*[METHODNAME]*/(/*[PARAMLIST]*/); /*[RETVALRETURN]*/ } AP 02/03
VI
Using Aspects for Configuration of Distributed Services
AP 02/03
40
Overview and Motivation Mobile systems are challenging: • Dynamically changing parameters of communication (Quality-of-Service)
• Varying computational power – among different mobile end systems (Notebook, Pocket PC, cellular phone)
• One-size-fits-all type of services are not acceptable • State of the art: device-specific information encoding – Different representations for the same device are typically not supported (i.e., image vs. text vs. voice) – No chance to react on changing communication settings AP 02/03
The Problem illustrated
AP 02/03
41
Towards Configurable ad-hoc Services for Mobile Users • XML-based description language for system configuration – Description of service profiles
• Separation of implementation and configuration • Toolset for automatic system configuration • Support for mobile devices in networks with dynamically changing communication settings • Proof-of-concept scenario using COM+ and Windows CE AP 02/03
How to Configure a Service? • Service: component-based software which delivers information upon client‘s request • Services are made of: – Components + attributes (i.e.; jpeg-filter with given compression) – Connectors (i.e.; RPC, shared memory interconnect, TCP/IP socket)
• Service configuration consists of: – Component instantiation and configuration – Selection of the appropriate interconnection mechanism (plumbing)
• XML-based configuration description – Rules for dynamic re-configuration when environment changes
AP 02/03
42
Configuration Process •
Configuration manager interconnects components as described in the choosen configuration profile IUnkown
IService
XML document
configuration manager
IConfigure
IConfigure
IConfigure
IConfigure
AP 02/03
The Distributed Control Lab – a configurable robotic system Variety of robot configurations • Different actuators/sensors • Experimentation with control algorithms • Coordinated actions of multiple robots
Dynamic reconfiguration as a safeguard mechanism AP 02/03
43
Distributed Control Lab – Structure Browser
RemoteDCL Systemsicht der Softwareebenen der Experimente sowie RCX-Hardware
Webserver and MasterControl
IDCLControl
IDCLControl
RemoteDCL
DCLControl Pendel
DCLControl RCX
Configuration
IRCXRunner
VideoStreamer VideoStreamer VideoStreamer
IlegOSCompile legOSCompile
RCXRunner RCXRunnerControl
legOSCompileControl
Tracker Component
Webcam Webcam Webcam
File Storage LNPOI
GCC Compiler
DLL
Tracker
Security Checker
LEGO Tower RCX RCX Tracking Hardware (Webcam)
AP 02/03
Distributed Control Lab – Interfaces «interface» IDCLControl +DownLoad(inout file : string) : string +Start() : string +Stop() : string +SendOpCode(inout code : string) : string +GetStatus() : string
«interface» IRegistration +ControllerRef() : string +Finalize() +StartController() : bool
DCLControlRCX +ControllerRef() : string +Finalize() +StartController() : bool +DownLoad(inout file : string) : string +Start() : string +Stop() : string +SendOpCode(inout code : string) : string +GetStatus() : string 1
1
-Controller
-RcxRunner
«interface» IRCXRunnerControl +getStatus() : string +download(in fileRobot1 : IFile, in fileRobot2 : IFile) +start() +stop() +send(in message : string, in to : int) +init(in homeRunner : IFile)
1
-Controller
1
-CompileControl
«interface» ILegOSCompileControl +setCompilerPath(in compilerPath : string) +setOutputPath(in outputPath : string) +createBinary(in fileObject : IFile) : IFile +createFileFromString(in text : string) : IFile +getErrorMessages() : IMessageContainer +setCompilerOptions(in param : string)
AP 02/03
44
Web-based Robotics Experiments
Internet + .NET Remoting
Wireless LAN
Infrared
Communication modul
CONTROLLER Controls actions to prevent robot destruction
ASP.NET & .NET Remoting Use hands
Drive
www.dcl.hpi.uni-potsdam.de
Trike API
Caterpillar API
Walker API
Load Programm
AP 02/03
Dynamic Re-Configuration – Experimental Evaluation of .NET How expensive is dynamic re-configuration? • Measurements based on Pentium High Resolution Performance Counter (Win32-Api) • Measurement overhead (unmanaged call) – within the µ-second range • Example appplication: Client/Server system – Server propagates attribute via get-method
• 5000-10000 measurements per experiment
AP 02/03
45
External event changes execution environment Measurement
Time
Polling period Reconfiguration
timeline
Configuration manager notices change Loading of new components Adjustment of new components‘ attributes Blocking of connection requests Adjustment of component‘ attributes Interconnection of components Initialization of new components Removal of old components Reaction on env. change Detection of env. Change Reconfiguration phase Blackout period
AP 02/03
Probability distribution of experimental results
- Adjustment of a single attribute value - Local application - Client/server are separate processes Blackout periods
Blackout period in ms
AP 02/03
46
Probability distribution of results
Adding a remote component residing in a separate process
Adding a component Blackout-period
Duration of re-configuration
Duration in ms
AP 02/03
Duration in ms
Blackout period Reconfiguration period Loading of Scaling addl. components up
Number of components involved
AP 02/03
47
Foucault‘s Pendulum
AP 02/03
VII Dynamic Aspect Weaving - Dealing with Contrary Aspects AP 02/03
48
Dynamic Aspect Weaving • Aspect weaving typically happens at compile time • Handling multiple aspects is difficult – Each aspect constraints the solution space – Some aspects may not be required for a particular setting
• Evaluating aspect information at runtime may help – Postpone aspect-weaving phase until runtime – Component may be deployed with all, some, or no aspect information being considered at all
• Resource-consuming aspect code can be avoided – When not required for a particular deployment scenario AP 02/03
Inteconnecting Aspect-code and functional code .NET library implements classes and attributes for AOP • Aspect: – Base class for all aspects
• Weaver: – A dynamic aspect weaver
• Call: – An attribute used to define connection points
• AspectContext: – Object context which can be used to invoke instance methods AP 02/03
49
Example: A Distributed Mandelbrot-Set computation
• AOP is used – to control distribution of data and compution – to optimize memory usage
• Both aspects have contrary goals • Tradeoffs and deployment environment are known only at runtime AP 02/03
Mandelbrot-Set: The Memory Aspect public class Memory : Aspect { [Call(Invoke.Instead)] // connection point public void Calculate(string filename, double x1, double y1, double x2, double y2, int xRes, int yRes) { double dStep=(y2-y1)/((double)yRes); // split up in lines for(int i=0;i