Presentation is loading. Please wait.

Presentation is loading. Please wait.

.NET Framework Advanced Topics

Similar presentations


Presentation on theme: ".NET Framework Advanced Topics"— Presentation transcript:

1 .NET Framework Advanced Topics
Name Title Department Company This session will provide an overview of the .NET Framework advanced topics on Reflection, Remoting, and Serialization.

2 Prerequisites This module assumes that you understand the fundamentals of: Programming Variables, statements, functions, loops, etc. Object-oriented programming Classes, inheritance, polymorphism, members, etc. C# .NET Framework Class Library

3 Learning Objective Provide an overview on several advanced .NET Framework topics KEY MESSAGE: .NET Framework and C# Language SLIDE SCRIPT: SLIDE TRANSISTION: Agenda ADDITIONAL INFORMATION FOR PRESENTER:

4 Agenda Reflection Remoting Serialization

5 Reflection Looking back: Automation and COM type information
Reflection core concepts Exploring metadata Detail information Attributes Putting it together The objective of this section 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.

6 Reflection Looking Back: Automation
TypeLibraries contain type information Exploration through ITypeLib/ITypeInfo Attributes describe behavior of elements For example, directionality of parameters For example, method role (instance method, property) Dynamic Invocation using IDispatch Type system supports most popular simple types Dynamic types using VARIANT Arrays passed using SAFEARRAY Strings expressed as BSTR 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. 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 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.

7 Reflection Core Concepts
Metadata Single location for type information and code Code is literally contained within type information Every .NET object can be queried for its type Type metadata can be explored with Reflection Dynamic Type System Highly dynamic and language independent Types may be extended and built at run time Allows on-the-fly creation of assemblies .NET Compilers use .NET to emit .NET code .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 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.

8 Reflection Exploring Metadata
[serializable] public class Person : { public event OnSaveChange onsv; public Date DOB; public string FirstName; public string LastName; public string Name { get { return FirstName + " " + LastName; } } public void Person(string First,string Last) { FirstName=First;LastName=Last; } public bool Save() { System.Type t = this.GetType(); foreach( FieldInfo f in t.GetFields() ) { ... } } System.Type Attributes Events Fields 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. Properties Constructors Parameters Methods

9 Reflection MetaData Samples
// Test sample class public class Test { private int n; public Test(int a) { n=a;} ... } //Retrieve the Type object public static int Main(string[] args) { Type type1 = typeof(Test); Test t1 = new Test(0); Type type2 = t1.GetType(); Console.WriteLine(“type of t1 is (0)”, type2); return 0 This example illustrates the basic concepts of the Reflection: the typeof operator and the GetType() method. A Type object can be retrived using the GetType() method or the typeof operation, depending on whether you are using a class name or an object reference. The output from this piece of code will be: “Type of t1 is Reflect.Test”

10 Reflection System.Type
Provides access to metadata for any .NET type Returned by System.Object.GetType() Allows drilling down into all facets of a type Category: Simple, Enum, Struct or Class Methods and Constructors, Parameters and Return Fields and Properties, Arguments and Attributes Events, Delegates, and Namespaces Access to meta-data 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.

11 Reflection Type and Instances
Type Safety First! Type checking at run time C#: if (o is Customer) { … } VB: If TypeOf o Is Customer Then … End If Dynamic Invocation through Reflection Support for late binding: MethodInfo.Invoke() FieldInfo.SetValue() 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. 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().

12 Reflection GetMethods Example
//Get a list of methods supported by a class public static int Main(string[] args) { Type type1 = typeof(Test); MethodInfo[] minf = type1.GetMethods(); foreach (MethodInfo m in minf) //Print out the method name and whether it is public Console.WriteLine(“Name: “+ m.Name + “,” + ((m.IsPublic) ? “ public” “ “”) + ((m.IsVirtual) ? “virtual” : “”); //Get the list of paramerters ParamerterInfo[] pi = m.GetParameters(); foreach (ParameterInfo p in pi) Console.WriteLine(“ “ + p.ParameterType + “ “ + p.Name); return 0 } This example shows a way to get a list of methods supported by a class by using the GetMethods() method. Note that the .NET Security mechanism will only allow a class to obtain the public members of another class, unless it has been given ReflectionSecurity permission.

13 Reflection MemberInfo
Base class for all "member" element descriptions Fields, Properties, Methods, etc. Provides member kind, name, and declaring class 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. MethodBase ParameterInfo FieldInfo EventInfo PropertyInfo MethodInfo ConstructorInfo

14 Reflection Dynamic Creation Example
public static int Main(string[] args) { Type type1 = typeof(Test); //Instantiate the Test Object object[] ctorParams = new object[] (1); object obj = Adtivator.CreateInstance(type1, ctorParams); //Invoke a method object[] ctorParams = new object[] (3); int res = (int)type1.InvokeMember(“Amethod”, BindingFlags.Default|BindingFlags.InvokeMethod, null, obj.methodParams); return 0 } One very useful feature related to reflection is the ability to create objects dynamically and call methods on them. You can specify which class you want using a Type object, or by giving the name of an assembly and a class as stings, so this even makes it possible to get the name of a class from the user and create an object of the appropriate type. You can them interact with the new object just as if you’d created it with new, and use reflection to find out just what you’re dealing with and what it can do. This example shows how it works. The code creates an instance of our Test class, and invokes a method on the object.

15 Reflection Attributes
Custom attributes are the killer-app for Reflection! Attributes enable declarative behavior Attributes allow data augmentation 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.

16 Reflection Attributes
[dbcolumn("Address1")] string Street; [dbcolumn("Postcode")] string ZIP; Map fields to database columns with FieldInfo.GetCustomAttributes() Mark class as serializable Type.GetCustomAttributes() [serializable] class Person { ...

17 Reflection The Bigger Picture
Types know their module; modules know their types Modules know their assembly and vice versa Code can browse and search its entire context Assembly Module Module Module Class Struct Delegate 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. Constructor Class Class Method Interface Interface Method Field Class Interface

18 Reflection Introducing System.Reflection.Emit
Full representation of physical structure Allows building modules and assemblies at run time Transient code only used at run time Persistent code for reuse Create classes and types, and emit IL Used by .NET compilers to build .NET apps 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. 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.

19 Reflection Visual Studio.NET and Reflection
Toolbox Component Class Description Properties Window DefaultValue Help Localizable Designers 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. ReadOnly Help ComponentModel Attributes

20 Reflection ASP.NET and Reflection
IIS ASP.NET runtime Assembly exists, same time stamp? File exists? 1 2 3 No? Compile 2a Run <%Page codebehind="pg"%> <html> <body> <asp:label/> <asp:textbox/> </html> </body> ASP.NET compiler 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. Page Assembly Reflection class pg : Page { ... }

21 Reflection Summary Reflection = System.Type + GetType()
Explore type information at runtime Enables attribute-driven programming Use Emit classes to produce .NET assemblies Bottom line: Fully self-contained structural model 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.

22 Agenda Reflection .NET Remoting Serialization

23 .NET Remoting Overview Remoting architecture Context and interception
Serving and accessing objects Putting it together

24 .NET Remoting Looking Back: Remoting in COM(+)
All Objects implement IUnknown interface Dynamic exploration of object features Lifecycle control with reference counting DCOM: Object-RPC based on DCE Wire Format Marshaling through MIDL generated Proxies/Stubs Automation: Dynamic binding through IDispatch Servers locally advertised in Registry Activation "on-demand". Servers launched at client request Objects created through class factories All Objects implement IUnknown interface Every COM object implements the IUnknown interface. IUnknown provides two basic services common to all objects: it allows for the dynamic exploration of object features and provides lifecycle control through Reference counting. DCOM: Object-RPC based on DCE Wire Format COM's wire format is DCOM, which is an object RPC mechanism based on DCE, the distributed computing environment, which was an initiative to create a large-scale interoperability infrastructure in the early 1990s. DCOM uses the IUnknown interface to exchange interface references and switch between interface types. Marshaling through MIDL generated Proxies/Stubs Marshaling, that is the serialization of data for transfer, is done through proxies and stubs that are code generated by the MIDL compiler, which takes interface definition language (IDL) files as input that describe interfaces, method signatures and the rules how they should be marshaled over the wire. The generated code is emitted in the "C" language and compiled into DLLs. Alternatively, dynamic interfaces can be exposed through the IDispatch interface, which is designed to be consumed by scripting languages or rapid application development environments. Servers locally advertised in Registry COM servers are locally advertised in the registry and every client that wants to use such servers and has no code that is explicitly aware of dealing with a remote server, which is not necessarily the recommended model for COM, must have a partial mirror copy of these registry entries. Activation "on-demand". The server activation model is component oriented. Servers are launched at client request and objects are created through class factories.

25 .NET Remoting Scenarios
Web Services Anywhere Expose Web Service endpoints from any process over any transport (pluggable channels) using any payload encoding (pluggable serialization formatters SOAP and Binary provided in the box) SOAP=HTTP+XML Web Services Anywhere. Expose WebService endpoints from any process e.g console app, GUI app, NT Service, IIS etc. Over any transport (pluggable channels) using any payload encoding (pluggable serialization formatters SOAP and Binary provided in the box). SOAP=HTTP+XML is the sweet spot. Full support for SOAP 1.1 including but not limited to: SOAPAction, SOAP Fault, SOAP Envelope, SOAP Headers, SOAP Body with Section 5 encoding including: primitives, enums, single dimension arrays, multi-dimension arrays, jagged arrays, structs, objects by value, trees as well as graphs of objects. SOAP over HTTP, SOAP over SMTP. Support for SOAP Section of SDL to describe the WebService and full Runtime type system fidelity. Generates Service Descriptions from class descriptions (metadata) and COM objects. Consumes Service Descriptions and generates metadata and proxies. A rich interception model is provided, that allows for developers to plug in their own behavior as message flow inbound and outbound from the application.. CLR Object Remoting. Built on top of Web Services Anywhere. Full Common Language Runtime type system fidelity (e.g. class hierarchies, constructors, delegates, interfaces, methods, overloaded methods, properties, fields), Marshal by Value (make a copy) and Marshal by Ref (pass an ObjRef) objects between Web Services over the wire using any of the pluggable channels. Distributed Identity, Activation, Lease based Lifetime and CallContext (flow objects in the SOAP Headers independent of the Parameters). A TCP Channel (using sockets) with a Binary Encoding is provided for those folks who want to get down to the metal.

26 .NET Remoting Scenarios
CLR Object Remoting Built on top of Web Services Anywhere Full Common Language Runtime type system fidelity Marshal by Value (make a copy) and Marshal by Ref (pass an ObjRef) objects between Web Services over the wire using any of the pluggable channels. Distributed Identity, Activation, Lease-based Lifetime and CallContext A TCP Channel (using sockets) with a Binary Encoding is provided

27 .NET Remoting Core Concepts: Federated Service Model
Trading Partners XML .NET Building Block Services EDIFACT X12 Open Standards: TCP/IP XML HTTP SMTP SOAP WebService Providers Financial News B2B Enterprise Applications The Federated Services Model Before we dive into the technical details of the .NET Remoting model we are going to look at some other design motivations besides adjusting the Remoting model to the Internet reality. At the heart of Microsoft's third generation Internet vision is the "federated services" model. The scope and requirements for enterprise application design have changed dramatically with the universal connectivity provided by the Internet. Businesses require that their applications for sales, procurement, knowledge management, accounting and their e-commerce storefronts exchange information amongst each other and with external services. Such external services may be the systems of trading partners, which accept and send business documents in XML or EDI formats or services from providers that provide financial information, news or other industry related data. Common to all these services, if they are provided over the Internet, is that they must be built open standards to allow for maximum degree of interoperability. The overall Microsoft .NET strategy with its XML centric enterprise servers such as Microsoft SQL Server 2000, Microsoft Exchange 2000 and Microsoft BizTalk Server 2000, the .NET building block services such as Microsoft Passport and other still-to-be-announced offerings and the .NET framework with its native support for Web services and high-productivity development environment for enterprise applications was designed to allow software developers to meet these requirements. The portion of the overall strategy that we're covering here, the .NET framework, reaches out to services on other machines or other business domains through the Remoting subsystem. When .NET Remoting operates in the Internet context, it is using HTTP as its fundamental transport protocol, which, in turn, is implemented on top of TCP/IP. Messages that are exchanged between endpoints are expressed in XML and wrapped into SOAP envelopes. In effect, .NET Remoting builds on a layered model of open Internet standards which allows .NET solutions to be easily integrated into the context of larger enterprise IT infrastructures and enables the consumption of services from any other system with .NET. Website Sales Procurement SQL Server XML .NET Enterprise Servers BizTalk Messaging Knowledge Management Accounting Organization Exchange WebStorage

28 .NET Remoting Application Domains
Isolated execution space for applications Independent of O/S concept of thread, process Process Process AppDomain AppDomain AppDomain Object Object In COM, marshaling and in-process and out-of-process Remoting happens all over the place. Message calls get marshaled between machines, processes, COM+ contexts, threads and between COM Apartments. Especially the COM Apartment model has caused quite a lot of headaches for many programmers, although it was initially designed to make development easier by hiding the details of process of threads synchronization from the developers. .NET simplifies this model. Marshaling and Remoting of objects occurs in exactly two cases: when messages across application domain boundaries or, as we will see a bit later, context boundaries. A .NET Application consists of one or more assemblies and runs within an Application Domain (also known as an AppDomain). Isolated execution space for applications, Independent of OS concept of thread, process Application domain is an isolated execution space for applications. The Application domain model is independent of the operating system concept of threads or processes. A single operating system process can host multiple "AppDomains". Still, the application domains are fully isolated entities that share nothing but the common host process. When application domains exchange messages, independent of whether there are located within the same process, in different processes or even on different machines they do so through .NET Remoting. Object Object Object

29 .NET Remoting Remoting Context
Derived from COM+ context idea But: Remoting Context != COM+ Context Encloses objects with same functional context Carries shared properties that describe behavior AppDomain Object Context Context Remoting boundary Derived from COM+ context idea The .NET Remoting context is a special boundary around objects that share the same runtime behavior. This very similar to the COM+ concept of contexts. If a COM+ component that is marked as to require a transaction create another COM+ component that is configured in the same way, they will share the same context and with that the same transaction. This is similar in the .NET Remoting context. If two context-bound objects share the same runtime properties, they also share the same context. However, while both concepts are very similar, it is very important to stress that the COM+ context is in no way related to the .NET Remoting context. Even if the also programming model for the COM+ service integration into .NET (that is not going to be covered in this module) looks strikingly similar, you must strictly differentiate between the two. The two models might converge at some future point in time, but in initial release of the .NET Framework SDK it is not so. Encloses objects with same functional context Generally speaking, the Remoting context encloses objects with the same functional context. This means that all objects that are contained in the context behave identical in some certain ways. This behavior is controls by properties, which are installed into the context using attributes that are specified on the object classes. You are going to see more of this later in this lesson. Carries shared properties that describe behavior The properties that exist on the context are shared by all objects and describe or even actively control or provide the behavior. Every call that passes a context boundary is processed by the Remoting infrastructure. Object Object Object Object Object Object RqTx Sync Thrd

30 .NET Remoting “Remote” vs. ”Local”
"Local" are all objects within the same AppDomain All other objects are "Remote" Even objects in the same process! Context-bound objects: "Local" if they share the same context "Remote" if they are in different contexts "Local": Not marshaled, immediate object calls "Remote": Marshaled, calls through proxies "Local" are all objects within the same AppDomain, all other objects are "Remote" So, the terminology gets quite a bit easier. We do not have to talk about different Apartments and exactly in which threads objects are located, but only have two terms: "remote" and "local" in the very simple sense that local objects are "nearby" and the remote objects are "further away". By principle, all objects within the same application domain are "local". All other objects are "remote", even if the application domains are hosted within the same process. Context-bound objects Context-bound objects are a bit special. Towards each other, all objects that share the same context are "local" and objects that are located in other contexts are "remote". "Local": Not marshaled, immediate object calls If you call a method on a local object, the call is executed immediately through the application stack without any marshaling taking place. "Remote": Marshaled, calls through proxies When you call a remote object, the call is routed through a proxy and all arguments are marshaled. Important: For this entire lesson the term "method" shall be seen as a synonym for all fields, properties, events, delegates and methods that class may expose. With .NET, you only have to memorize two different Remoting boundaries: the application domain boundary and the context boundary.

31 .NET Remoting Building a Remote Application Example
Writing a well-known Web service using System; namespace HelloService { // Well Known WebService object public class Hello : MarshalByRefObject { // Return the name prefixed with a string public String HelloMethod(String name) { Console.WriteLine("Hello.HelloMethod : {0}" +, name); return "Hi there " + name; } Writing a well known WebService object is a simple as declaring a class and implementing the methods for the class. The class must derive from System.MarshalByRefObject or any of its children, this allows Microsoft .NET Framework Remoting.NET Remoting to optimize for Remoting objects. The Remote Application is published by hosting it in ASP.NET or a host such as the sample MyHost. Once the Remote Application is published it can start processing messages.

32 .NET Remoting Hosting Example
ASP.NET hosting example Creating an IIS root that points to the app directory Adding a "Remoting.cfg" configuration file Remoting.cfg for the HelloService Name#HelloService WellKnownObject#HelloService.Hello#HelloService#HelloService/Hello.soap#SingleCall Hosting the Remote Application in ASP.NET involves creating a IIS root that points to the application directory and adding a "Remoting.cfg" configuration file to that directory. The executable or DLL containing the remote object should be placed in the bin directory under the directory the IIS root points to. It is important to note that the IIS root name should be the same as the Application name specified in the config files. The Remoting configuration file is automatically loaded when the first message arrives in the application. Remoting.cfg for the HelloService Name#HelloService WellKnownObject#HelloService.Hello#HelloService#HelloService/Hello.soap#SingleCall Name The 1st line indicates the application name, The format is: Name#Name of the Application The application name is HelloService. WellKnownObject The 2nd line indicated the well known object that is published for this application. The format is: WellKnownObject#[FullTypeName]#[AssemblyName]#[ObjectURI]#[ObjectMode] Hosting in MyHost MyHost is a sample managed console EXE that loads a Remoting Configuration file and is useful for debugging purposes since it can be started from the command line and run under a debugger. Hosting the Remote Application in MyHost involves creating a Remoting configuration file and specifying it as a command line argument to MyHost. HelloService.cfg for the HelloService Name#HelloService WellKnownObject#HelloService.Hello#HelloService#HelloService/Hello.soap#SingleCall Channel#System.Runtime.Remoting#System.Runtime.Remoting.Channels.HTTP.HTTPChannel#ports=8085 An example of starting MyHost and specifying the HelloService.cfg MyHost -cfg HelloService.cfg

33 NET Remoting Hosting Example
MyHost (a managed console app) example Name#HelloService WellKnownObject#HelloService.Hello#HelloService#HelloService/Hello.soap#SingleCallChannel#System.Runtime.Remoting#System.Runtime.Remoting.Channels.HTTP.HTTPChannel#ports=8085

34 .NET Remoting Using Configuration and New Example
using System; using System.Runtime.Remoting; using HelloService; public class SimpleHello { public static void Main(String[] args) { String name = "Bill"; RemotingServices.ConfigureRemoting("MyHello.cfg"); Hello hello = new Hello(); String result = hello.HelloMethod(name); Console.WriteLine("Hello.HelloMethod returned: " + result); } Contents of MyHello.cfg Name#MyHello Assembly#HelloService#HelloService#Hello= RemoteApplication#HelloService# Channel#System.Runtime.Remoting#System.Runtime.Remoting.Channels.HTTP A proxy can be obtained by calling "new" on some class. To use "new", a Remoting Configuration file must be loaded. The file can be loaded by calling RemotingServices.ConfigureRemoting. Once the Remoting configuration is loaded, future objects created for the class Hello will be created at the well known URL specified in the configuration file. An application hosted in ASP.NET can send messages to a Remote Application. The Remoting Configuration is automatically loaded by remoting. That said one RemoteApplication hosted in ASP.NET can send messages to another Remote Application hosted in ASP.NET.

35 .NET Remoting Architecture
What: Messages Where: Channels How: Formatters Marshaling Concepts Proxies In this section we are going to look at the fundamentals of the Remoting architecture. Specifically we are going to explore what messages are, how channels control where messages go, how formatters are used to render the messages in a special wire format and how the .NET Remoting infrastructure uses these elements to create a transparent programming experience with dynamic proxies.

36 .NET Remoting What to Communicate: Messages
Messages are objects that implement IMessage IMessage: Simple dictionary of key/values pairs .NET Message Types: Construction call messages, response messages Method call messages, response messages Invocation Styles Synchronous: Request with immediate response Asynchronous: Request with delayed or no response Messages are objects that implement IMessage From a programming standpoint, messages are objects that implement the IMessage interface. IMessage: Simple dictionary of key/values pairs The IMessage interface is a very simple dictionary of key/value pairs. The message dictionary may contain any number of entries, each individually keyed by a string. The values that are held in the message may be of any .NET object type. The Remoting infrastructures task is to remote these dictionaries across Remoting boundaries. .NET Message Types To make implementation of method calls consistent, .NET defines a few additional message types that are all derivatives of the IMessage interface. The message types include construction call messages and responses and method call messages and responses. Internally, the only difference between a "plain" message and, say, a method call message is that the method call message uses a set of predefined dictionary entries. Invocation Styles There are two known invocation styles for method calls and therefore two "delivery modes" for messages: If messages are being delivered synchronously, they represent a request that expect an immediate response. If they are delivered asynchronously they represent a request that expect a delayed or no response at all.

37 .NET Remoting Where to Communicate: Channels
Channels transport messages .NET built-in channels: TCP, HTTP, SMTP Establish endpoint-to-endpoint communication Channels can listen for and send messages Listener implements IChannelReceiver Sender implements: IChannelSender Makes no assumptions about endpoint architecture Channels transport messages Channels are responsible for transporting messages. As such, they are an abstraction of a specific transport protocol and find that product called to the .NET Remoting infrastructure. The .NET framework comes with three built-in channels: A TCP channel that uses raw TCP/IP sockets, a HTTP channel that uses the .NET HTTP infrastructure and a SMTP channel that implements asynchronous messaging. The channel model is also extensible; if you require support for other transport protocols, you can implement your own channels and use them with all the parts of the .NET Remoting infrastructure. Establish endpoint-to-endpoint communication A channel is responsible for establishing endpoint-to-endpoint communication. The transport portion of the channel implementation receives a formatted data stream and is responsible for getting that formatted data stream to the other side. Channels can listen for and send messages Channels can listen for messages and send messages. So, the Illustration that we are showing here maybe a bit misleading, because it may functions in both directions. A client may send a message one-way through the channel to the server, and for the response the channel effectively turns around. Although that may be a bit leaping ahead, we should already make clear at this point, that this model also supports callbacks. If you pass an object reference through a channel and the receiver holds on to that reference and uses it for callbacks at a later point in time, the call that messages are relayed through the original channel. The listener portion of a channel implements the IChannelReceiver interface and the sender portion implements the IChannelSender interface. A channel is only bi-directional it implements both interfaces. If you want, for some reason, implement a receive-only channel you only need to implement the IChannelReceiver interface and IChannelSender for a send-only channel, respectively. A receive-only channel can, of course, not relay any callbacks. Makes no assumptions about endpoint architecture The most interesting point about the channel architecture is though, that makes no assumptions about how the opposite endpoint is implemented. If the remote endpoint uses a compatible SOAP implementation that runs on some Unix variant the channel will be just as happy to deliver the message as if the endpoint was a native .NET application. Channel Server Client "Proxy" Dispatcher

38 .NET Remoting How to Communicate: Formatters
Formatters serialize .NET objects into wire formats Used dynamically by channel architecture Selection based on MIME type. Register globally: CoreChannel.RegisterChannel() Built-in: SOAP and Binary Formatter Custom Formatters allow talking to any endpoint Formatters serialize .NET objects into wire formats We have learned that messages are dictionaries and channels are able to remote data streams. The formatter’s task is to convert dictionaries into data streams and vice versa. More precisely, the transform the method call into the appropriate wire format message. Used dynamically by channel architecture Formatters are dynamically used by the channel architecture. The configure a channel to transport messages in a certain wire format by setting a MIME type on the channel and the channel will pick the appropriate formatter that is able to render messages into the desired format. On the receiving end, the formatter acts as a deserializer component that understands a certain wire format and is able to translate that into a .NET message. New formatters are registered with the system through the static RegisterChannel() method on the CoreChannel class that resides in the namespace System.Runtime.Remoting.Channels.Core. Built-in: SOAP and Binary Formatter The .NET framework has two built-in formatters. The binary formatter uses a very compact binary format that is designed for best performance in high-speed LAN environments and to interconnect .NET systems. The SOAP formatter uses the XML-based Simple Object Access Protocol to transport object calls over the Internet and to integrate .NET systems with all other systems in the enterprise environment. The built-in formatter types are, of course, pre-registered with the system. Custom Formatters allow talking to any endpoint The formatter model is extensible. If you want to integrate systems directly using other wire formats (to name a few: IIOP, RMI, ORPC, XP, XML-RPC) you can implement your own formatters and have .NET systems talk natively to any endpoint you want. SOAP, Binary, Custom Decode from wire format Channel Encode into wire format

39 .NET Remoting Objects To Go: Marshaling
Definition: Packaging Data for Transfer For objects passed as arguments, return values Marshal-By-Value Entire object is packaged as-is Copy is transferred to destination No link between copy and original Marshal-By-Reference Just a reference to an object is packaged Reference is transferred to destination "Proxy" object links destination with original Definition: Packaging Data for Transfer Now we need to take a closer look at the message content. Since the ultimately want to remote method calls, the message will likely contain inbound and outbound arguments as well as return values. The serialization of these arguments into the appropriate wire format is the job of the formatter. However, to dealing with object-oriented system here you will not one to flatly pass all object data by value. Instead, you will want to be able to pass references to objects that reside in your own application domain or context. Making of this distinction is the objective of the marshaling rules. The word "marshaling" has its roots in the military. The marshal is the one that orders the troops for the parade. Likewise, in computing, the marshal is the one that orders the bytes for transmission. A simple synonym for marshaling would be "packaging data for transfer". For objects passed as arguments, return values Marshaling applies to all objects that are passes as input arguments or returned as return values or output arguments for object fields, properties or methods. Since everything is an object in .NET, marshaling applies to everything if you're crossing a Remoting boundary. As aforementioned, there's a certain set of rules that determines whether an object is passed by reference or by value. Before we get to these rules, we will first inspect the fundamental differences between marshaling by value marshaling by reference. Marshal-By-Value When you marshal an object by value, the entire object is packaged as-is and the copy is transferred to the destination. With that, there is no link between the copy and the original. Marshal-By-Reference Marshaling by reference just causes a reference to the object being packaged and sent to the destination. Once a reference arrives at the destination, the Remoting infrastructure will automatically create a proxy object that mirrors the shape of the original object and passes this proxy on to the receiver. The receiver can then make calls on the proxy, which are routed through the channel back in the opposite direction.

40 .NET Remoting Concepts: Agile and Contextful
Agile Objects Independent of Context Called directly from any AppDomain or Context Do not use channels Unbound Classes: Travel between AppDomains, marshal-by-value AppDomain-Bound Classes: Reside in a single AppDomain, marshal-by-reference Contextful Objects Bound to AppDomain and Context Marshal-by-reference outside of context Now we get to the marshaling rules. There are three fundamental types of classes that fit into two categories: agile objects and contextful objects. The simple difference between the two is that a contextful objects live inside a context and agile objects do not. Agile Objects So, because there is never a Remoting boundary between the client and agile objects within the scope of an application domain, calls to agile objects are always direct and dispatched through the stack. However, this behavior depends on the scope of the code that created the agile object and the marshaling type, of course. If the class of the agile object is "unbound", it is always marshaled by value (or even never marshaled at all, if it cannot be serialized by a formatter). That means that as soon the object crosses a Remoting boundary is cloned. This behavior applies to all the value types within the .NET framework. All classes are "unbound" by default. This concept is not entirely identical to the "value" and "reference" type difference made in the common type system (CTS). The differentiation of the CTS applies to all method calls, independent of whether they are subject to Remoting or are dispatched through the stack. While CTS value types are always marshal by value in Remoting as well, the respective equivalence is not true for reference types. So when it is being said that all classes are "unbound" by default, and always marshaled by value once they hit a Remoting boundary. This concept is great to optimize distributed systems but must be used with utmost care. Because unbound objects are the default, data is always replicated across boundaries. This greatly reduces the round trips between client and servers, but may be a problem for you data integrity if you are not aware of this behavior. The ADO.NET DataSet, for instance, is an unbound class whose code is always executed locally. Therefore, the design pattern that you can find implemented in Visual Studio .NET is that there is always a retrieval function that returns an entire dataset and an "update" method that receives a dataset. With that, the dataset can be safely replicated to a remote client, managed there by only using local calls and is replicated back to the server when it is passed as an argument to the "update" method. If an unbound class has no serialization support, it will never be marshaled and will cause the method invocation to fail, if it as used as an argument or return value. Adding serialization support to class requires setting the "[serializable]" attribute on the class and, optionally, implementing the ISerializable interface of the class. This allows the formatter to use the serialization support of the runtime to render the class content in XML, which can then be translated into the formatter's native to wire format. Classes that are bound to an application domain, are seen as to "live" within that application domain and have a distinct identity. Therefore, they are always marshal a reference. You must signal this wanted behavior to the Remoting infrastructure by deriving your class from the base class MarshalByReference. Such classes do not have or require serialization support, of course. Contextful Objects Contextful objects fall into the second category. A contextful object is bound to both its context and the application domain it is hosted in. This is signaled to the Remoting infrastructure by deriving the class from the base class ContextBoundObject. Such objects are always remoted across context boundaries. Agile objects that are referenced by context-bound objects are always called directly, unless a reference to them has become known to the context-bound object through the Remoting boundary.

41 .NET Remoting Proxies "Proxy" Definition Real Proxies
Object that acts locally on behalf of a remote object Looks like and accepts calls as if it were "real" Forwards them to the remote object Real Proxies Inherit System.Runtime.Remoting.RealProxy Are the communication layer for transparent proxies Transparent Proxies Built dynamically by real proxy Exact pass-through mirror of the remote object "Proxy" Definition The term "proxy" has already been mentioned a couple of times. Here we want to take a closer look at this concept. In general, a proxy is an object that exists and acts locally on behalf of a remote object. The proxy looks like and accepts calls as if it where the real object. It also exposes the same set of interfaces that original object exposes. However, the proxy does not process the calls locally, but sends them to the remote object it represents. This, at least, is the common understanding of the term "proxy". The .NET framework differentiates between two types of proxies: The real proxy and transparent proxy. Real Proxies A real proxy is an instance of a class that inherits from the abstract base class RealProxy, which is defined in the System.Runtime.Remoting namespace. The real proxy accepts messages (IMessage) through its Invoke() method and forwards them to the remote object. With this functionality the real proxies are the transport layer for transparent proxies. However, they do not only do the bulk of the work for the transparent proxies they also are the factories for them. The RealProxy base class is able to dynamically create a transparent proxy for any arbitrary .NET class-type and have that transparent proxy call the real proxy's own Invoke() method. Transparent Proxies A transparent proxy is a dynamically created block of code that exists in the client application domain (or context) on behalf of the remote object and exposes all of its features,

42 .NET Remoting Proxies Illustrated
Channel Client Server "Proxy" IMessageSink Transparent Proxy Builds MethodA() This diagram illustrates the dependencies between the real proxy and the transparent proxy as well as the message sink and the channel. Let us first assume we already have a transparent proxy that we can call. When we call the method "MethodA()" on the transparent proxy, it will format the method name and the arguments, if such are present, and forward them to the real proxy's Invoke() method. The real proxy will then (typically) drop this message into the IMessageSink of the channel through the sink's SyncProcessMessage() method. Since .NET makes no assumptions about the endpoint architecture, we're not doing this either, and just assume that the message will somehow be responded to. To once the real proxy receives the response message, it will pass the response message on to the transparent proxy, which will push the return values on the stack. With that, the caller will believe that it just called a local method. How is the real proxy built? When a channel receives a message that contains an object reference, the reference information also contains the type of the referenced object. With that type in hands it is creating a new RealProxy instance and asks it to create a new transparent proxy based on the metadata of that type. This transparent proxy is then passed on to the called method. MethodB() Real Proxy Invoke() PropertyQ PropertyP FieldX SyncProcessMessage() FieldY

43 .NET Remoting The Dispatcher
Located at the channel endpoint Receives messages Builds stack-frame from message content Invokes actual method on object Collects result and creates response message Located at the channel endpoint The dispatcher is the proxy's counterpart at the receiving end of the communication and located at the channel endpoint. The dispatcher capabilities are provided by the ChannelServices class and through its SyncDispatchMessage() and AsyncDispatchMessage() methods. Receives messages, builds stack-frame, invokes method When one of those two methods is called, the passed message object is decoded and the dispatcher will locate the object it that is to be called, dynamically create a stack frame that contains all arguments and will execute the requested method. If the dispatcher receives an object reference to will create a real proxy, ask real proxy to create a transparent proxy and push the reference to the transparent proxy onto the stack. Collects result and creates response message When the method call returns, it will collect the output parameters and the return value and create a response message with them. The response message is then being handed back to the caller.

44 .NET Remoting The Dispatcher Illustrated
Client Server Channel Dispatcher Actual method calls Object MethodA() Here's a graphical representation of what we just explained. The message arrives at the receiving end of a channel, is being the serialized and formatted into a message objects and this message object is passed to the ChannelServices.SyncDispatchMessage() method. The call is dispatched on the real object, all values that must be returned are being collected and sent back as a response through the channel. Dispatcher (ChannelServices) MethodB() PropertyQ PropertyP FieldX SyncDispatchMessage() FieldY

45 .NET Remoting Context Rules and Concepts
Contexts enclose "contextful" objects Classes derived from System.ContextBoundObject Behavior for class declared using context attributes Common context boundary is shared when Objects have identical attributes or Context attributes actively agree to deviations All objects in other contexts are "remote" Conceptually similar to AppDomain boundary Messages crossing boundary may be intercepted Chains of IMessageSinks allows hooks at any stage Contexts enclose "contextful" objects Let us recapitulate a few facts that we already know about contexts. The .NET Remoting context and closes contextful object. All contextful object must be derived from the System.ContextBoundObject class and classes behavior is controlled by the properties that are declared for the class using attributes. Common context boundary is shared Objects share a common context boundary when they have identical attributes or when the context attributes actively agree to deviations of attributes. Simply speaking, each attribute is being asked whether it is "okay" with the context. All objects in other contexts are "remote" All objects in other contexts are remote, regardless of whether they are located in the same application domain or not. The context boundary is conceptually similar to the application domain boundary. Messages crossing boundary may be intercepted The message is that the cross the context boundary may be intercepted and chains of IMessageSink interface implementations allow hooks at any stage.

46 .NET Remoting Context Attributes and Properties
Yes! Use existing context New System. ContextBoundObject No! Create new context Attribute 1 IsContextOK() ? ContextBound Class 2 Create object 3 This diagram illustrates the relationship between context attributes and context properties. When an instance of a context bound class is created, and the class is declared with attributes, the activation process for the new object works as follows: And creation time and before the objects constructor code is executed an instance of the attribute class is created and its constructor called. All arguments that you have provided for the attribute at declaration time are passed to the new instance at this point. In the next step (1), the runtime calls the method "IsContextOk()" on the attribute, passing a reference to the context from which the object was created. The attribute can now decide, whether the existing context can be used for the behavior that the attribute describes. The attribute will specifically return "false", if the property exists on the context that conflicts with its own settings and the intended behavior. If the response is "true" the new object instance will be placed into the existing context, otherwise a new context is being created. In the latter case (2), the runtime will call the method GetPropertiesForNewContext() on the attribute object, allowing it to install one or more properties into the newly created context. The runtime will call this method regardless of whether the attribute found the context to be acceptable -- if a new context is being created, the method is invoked for all attributes that exist on the class. Finally (3), the runtime places the new instance of the context bound to class into the new or recycled context. Object No! GetPropertiesForNewContext() ! Property

47 .NET Remoting Remoting Services
System.Runtime.Remoting.RemotingServices class Provides fundamental remoting infrastructure Remoting configuration Connecting to remote object instances Exposing "well known objects" System.Runtime.Remoting.ChannelServices Channel registration and management System.Runtime.Remoting.LifetimeServices Lease-based lifecycle management for objects System.Runtime.Remoting.TrackingServices Universal hooks for tracking remoting activities

48 .NET Remoting Exposing Well-Known Objects
.NET's activation model is very unlike COM's .NET rather resembles CORBA model (!) If there is no actively listening endpoint: no connection No surrogates, no registry, no location transparency EXE servers are not remotely activated Simplifies remoting greatly Expose well known object for clients to connect. Bound to known channels with known name. Does not use static registration, prog-ids or class-id. Can only expose "single call" or "singleton" objects

49 .NET Remoting Single Call and Singletons
"Single Call" Objects Object instance is created for each call on channel. Implements the stateless model of the web. "Singleton" Objects One shared instance provided for all clients Serves as "gateway" into stateful application Can mirror COM's class factory concept Object is created at registration time RemotingServices.RegisterWellKnownType WellKnownObjectMode.SingleCall WellKnownObjectMode.Singleton

50 .NET Remoting Server Setup Example
... HTTPChannel chan = new HTTPChannel(8085); ChannelServices.RegisterChannel(chan); RemotingServices.RegisterWellKnownType( "MyAssembleName", "MyNamespace.ServerClass", "MyEndpointURI", WellKnownObjectMode.SingleCall); Channel registration Object registration Registers the single-call endpoint: Channels and Objects are AppDomain-Global

51 .NET Remoting Activation Illustrated
tcp://server:8501/uriD TCP 8501 HTTP 8088 AppDomain RemotingServices.Connect() Identity Table Activator.GetObject() uriA uriB uriC uriD Key Points Serve up existing object instances: Activator.GetObject / RemotingServices.Connect Choice 1: Serve up the same instance for each method call (singleton) Choice 2: Serve up a new instance for each method call (singlecall) Serve up a new object instance for each Activation Request: CreateInstance / newobj / "placement new" May serve up the object instance in same AppDomain / Application, same Context May serve up the object instance in another AppDomain / Application AppDomain / Application may be in the same process, different process, different machine Allow the Application URI to be specified in configuration Allow the Application URI to be specified at the activation call site New objects are activated in an Application. An Application is hosted within an AppDomain. An application can be configured to hosted in a remote AppDomain, relative to the current application. If the object is activated in a remote application, then the actual object instance is created in the remote application appdomain. A whole assembly or an individual type within an assembly can be configured to be activated in a remote application. A type can be specified using Activator.CreateInstance to activate in a remote application. Activation happens in two stages: In the first stage, a decision is made regarding whether the current application is OK. If the answer is Yes, a local instance of the object is activated. This may involve running a constructor if applicable. If the answer is No, the object is created in the remote application's AppDomain (this is detailed throughout this specification). Activation in a remote application involves context attributes and properties. In both the stages, context properties of the current context and context attributes defined on the type e.g. Foo (hereafter referred to only as context properties) are involved. In the first stage, the context properties are asked if the current context is OK and the processing stops immediately after the first property that answers No. In the second stage, the context properties are passed the Message object that represents the Construction Call. Language binding Context o = Activator. GetObject(" o.methodCall(); Object Object o = new myClass(); o.methodCall(); Object Object

52 .NET Remoting Channel Programming Examples
// Registering a Channel public class SomeClass { HTTPChannel httpChannel; public void SomeMethod() { httpChannel = new HTTPChannel(); ChannelServices.RegisterChannel(httpChannel); } // Lookup all the registered Channels public class SomeClass { public void LookupAllChannels() { IChannel[] channels = ChannelServices.RegisteredChannels; for(int i=0;i<channels.Length;i++) { Console.WriteLine("ChannelName: " + channels[i].ChannelName); } } //. . . } There two examples illustrate the Channel programming tasks: Registering a Channel and Lookup all the registered Channels. The unregistering a channel is simply: ChannelServices.UnregisterChannel(httpChannel) .

53 .NET Remoting Proxy Programming Examples
Determining if an object is actually a proxy public class SomeClass { //. . . public void ProxyCheck(Object obj) { if (RemotingServices.IsTransparentProxy(obj) == true) Console.WriteLine("Is a proxy"); else Console.WriteLine("Is not a proxy"); } //. . . } Obtaining the RealProxy from a Proxy public class SomeClass { //. . . public void ObtainRealProxy (Object obj) { RealProxy realProxy = RemotingServices.GetRealProxy( obj); //. . . } These two examples illustrate the proxy programming tasks.

54 .NET Remoting Context Programming Examples
Context Local Data Store Allocated Slots Foo foo = new Foo(); // Allocate data slot on all contexts LocalDataStoreSlot dataslot = Context.AllocateDataSlot(); // Store foo in the Context Local Store Context.SetData(dataslot, oFoo); / Retrieve foo from the Context Local Store Foo foo2 = Context.GetData(dataslot); Writing your own context attribute public class MyContextAttribute : ContextAttribute, IContributeServerContextSink { . . . public IMessageSink GetServerContextSink(IMessageSink nextSink) { return new MyContextServerSink(nextSink); } . . . }; These two examples illustrate the context programming tasks. The first example shows how to allocate data slot on all contexts. A data store slot is allocated and returned. The data store slot is used to access the data slot. The data store slot is collected by the GC when all references to it are freed. The second example illustrates how to write your own custom context attribute. We can see how new context attributes such MyContextAttribute would look like. Note that MyContextAttribute derives from ContextAttribute. The context attribute implements the IContributeServerContextSink interface.

55 Agenda Reflection Remoting Serialization

56 Serialization What is Serialization? System.Serialization
Scenarios in Serialization Basic Serialization Custom Serialization

57 Serialization What is Serialization
Serialization is the process of converting an object, or a connected graph of objects, stored within computer memory, into a linear sequence of bytes Use the sequence of bytes in several ways: Send it to another process Send it to the clipboard, to be browsed or used by another application Send it to another machine Send it to a file on disk Let's clearly define what we mean by serialization. By Serialization we mean converting an object, or a connected graph of objects, stored within computer memory, and conventionally drawn on paper in two dimensions, into a linear sequence of bytes. That string of bytes contains all of the important information that was held in the objects we started with. We can go on to use that sequence of bytes in several ways. For example: Send it to another process (on the same machine) and use it to construct arguments to a method that is run in that other process. In this case, the sequence of bytes is copied from one location in the machine's physical memory to another – it never leaves the machine Send it to the clipboard, to be browsed or included in another application. As above, the sequence of bytes is transferred to another location in memory on the current machine. Send it 'down the wire' to another machine and use it to create a clone on that machine of the original object graph. As above, we might then use this object graph as an argument to a method call. In this case, however, the sequence of bytes is actually transferred outside of the originating machine. Send it to a file on-disk, so that it can be reused later.   (See, for example, the classic "Scribble tutorial" in "Using Visual C++" issued as part of the Visual C++ 6.0, and earlier).

58 Serialization Object Graph
What is an object graph? An object graph is a set of objects with some set of references to each other The most obvious problem is how to represent the links between the objects in the Serialized stream 3 Dog An object graph is a set of objects with some set of references to each other. The interesting question here is what problems does this bring for Serialization? The most obvious problem is how to represent the links between the objects in the Serialized stream. After all, the value held in the field of the in-memory object which links to another object is essentially a 32-bit address, which has meaning only in the owner address space (and may even change, 'beneath our feet', due to garbage collection). Serialization needs to allocate each object in the stream a number. So, for example, we have assigned arbitrary, small numbers to objects below, and shown the class of each: Then we can represent this graph of objects with a serialized stream like this: Dog, 3, ref 4, ref 7, ref 1 || Cat, 4 || Cat 7 || Mouse, 1, ref 9, ref 2 || Horse, 9, ref 4 || Duck, 2 4 Cat 7 Cat 1 Mouse 9 2 Duck Horse

59 Serialization How Serialization Works
Because run-time metadata 'knows' about each object's layout in memory, and its field and property definitions, you can serialize objects automatically, without having to write code to serialize each field The serialized stream might be encoded using XML, or a compact binary representation The format is decided by the the Formatter object that you call: Binary SOAP Custom Because the runtime metadata 'knows' all there is to know about each object's layout in memory, its field and property definitions, you can serialize objects automatically, without having to write code to serialize each field. The serialized stream might be encoded using XML, or a compact binary representation. The format is decided by the the Formatter object that you call. Pluggable formatters allow the developer to serialize objects in with the two supplied formats (binary and SOAP) or create their own. Serializetion can take place with any stream, not just a FileStream (see MemoryStream, NetStream, etc.) Serialization makes use of several classes, as follows: Formatter — Responsible for writing object data in some specified format to the output stream. This class is also responsible for driving the deserialization operation. ObjectIDGenerator — ObjectIDGenerator generates IDs for objects. It keeps track of objects already 'seen' so that if you ask for the ID of an object, it knows whether to return its existing ID, or generate (and remember) a new ID. ObjectManager — Keeps track of objects as they are being deserialized. In this way, deserialization can query the ObjectManager to know whether a reference to an object, in the serialized stream, refers to an object that has already been deserialized (a backward reference), or to an object that has not yet been deserialized (a forward reference). Each of these components is 'pluggable' — the programmer can provide alternatives

60 Serializaiton FileStream Example
class SerializeExample{ public static void Main(String[] args) { ArrayList l = new ArrayList(); for (int x=0; x< 100; x++) { l.Add (x); } // create the object graph FileStream s = File.Create("foo.bin"); // create the filestream BinaryFormatter b = new BinaryFormatter(); // create the BinaryFormatter b.Serialize(s, l); // serialize the graph to the stream } // end main } // end class This example shows how to perform default Serialization of a graph of objects, whose root is the arraylist l. This code serializes the graph to a FileStream:

61 Serializaiton Deserialize Example
using System; using System.IO; using System.Collections; using System.Serialization; using System.Serialization.Formatters.Binary; class DeSerialize { public static void Main(String[] args) { FileStream s = File.Open("foo.bin"); // open the filestream BinaryFormatter b = new BinaryFormatter(); // create the formatter ArrayList p = (ArrayList) b.Deserialize(s); // deserialize p.ToString(); // print out the new object graph } // end Main } // end Class DeSerialize This example shows how to perform default Serialization of a graph of objects, whose root is the arraylist l. This code serializes the graph to a FileStream:

62 Serialization Scenarios
Persistence Flat-File Persistence Remoting-By-Value Remoting-By-Reference Transacted Persistence Why would you want to use serialization? There are several very interesting scenarios that rely on serialization as component to it happening.

63 Serialization Persistence
To Persist an object or collection of objects means to make them somehow survive beyond the life of the process that holds them in its memory. Conventionally, the objects are saved onto a hard disk, within a file, a storage stream, or a database. Within .NET runtime, we will use the terms Persist and Persistence in the stronger sense of saving the objects to disk, and retrieving them afterwards, under the protection of transactions To Persist an object, or collection of objects, means to make them somehow survive beyond the life of the process that holds them in its memory. Conventionally, the objects are saved onto a hard disk, within a file, a storage stream, or a database. (They might also be Persisted into NVRAM, but that's an uncommon case with regular PC used in the office). However, within the runtime, we will use the terms Persist and Persistence in the stronger sense of saving the objects to disk, and retrieving them afterwards, under the protection of transactions. In this situation, the objects are most likely stored in relational databases, whose table layout does not parallel their layout in memory.

64 Serialization Flat File Persistence
The runtime provides a default text formatter (e.g., generating XML stream) for serializing an entire object graph to a file ArrayList l = new ArrayList(); for (int x=0; x< 10; x++) { l.Add (x); } Stream s = (new File ("foo.bin")).Open(FileMode.Create); BinaryFormatter b = new BinaryFormatter(); b.Serialize(s, l); s.Close(); Suppose we have built a simple, desktop, single-user application, such as a 2D drafting package. Suppose too that we have built our application using OO techniques, and represent the graphical objects as a graph of in-memory objects, with one object representing the root of the entire picture. What we would like, is a painless way to save the entire picture to a disk file, so that it will be there for us tomorrow when we reboot our PC. Before the runtime, each object would have to implement the Serialize (and corresponding Deserialize) method.   However, with the runtime, there is really no need to impose this burden on the application programmer. After all, the runtime maintains metadata at runtime that allows serialization code to 'discover' the types and values of all fields and properties that make up any object. So long as the runtime provides a default text formatter (and the current hot favorite is to generate and XML stream), then serializing an entire object graph to a file should be as simple the first code snippet. The obj argument represents the root of the object graph. (Note – this syntax is invented for illustration only. The actual APIs are described in the SDK. Similarly, in order to start up our App the next day, ideally we need only code a few lines as shown in the second code snippet. Stream r = (new File ("foo.bin")).Open(FileMode.Open); BinaryFormatter c = new BinaryFormatter(); ArrayList p = (ArrayList) c.Deserialize(r);

65 Serialization Remoting-By-Val and Remoting-By-Ref
Serialize a copy of a graph of objects and pass it to the remote process No guarantee that fields will be laid out in memory in the same order Rmoting-By-Ref On the remote node, we establish a transparent proxy – it behaves like the real object. However, any accesses of its fields are passed back to the original object. Serialization does not know how to create the proxy object. This is accomplished through the Remoting service using a Surrogate for that Remote-by-ref object. In disributed computing, we may want to execute a method, not within the current thread, but within a thread in a separate process on the same machine, or even a thread in a process on another machine. We speak of this as Remoting the method invocation. Suppose the method to be Remoted takes, as one of its arguments, an object which lies at the root of a graph of objects. If all objects in the graph are marked as remote-by-val, then we have to Serialize a copy of graph and pass to the remote process. For efficiency, remoting is investigating whether an object's fields can be Serialized, without also Serializing a specifier for each field. However, the runtime makes no guarantee that fields will be laid out in memory, in the same order, from one instantiation of an object to the next; even more so if these instantiations lie on different platforms, such as Windows NT versus WinCE. In some Remoting situations, certain objects may be marked as Remoted-by-ref. In this case, the original object remains where it is. On the remote node, we establish a transparent proxy – it behaves, for all the world, like the real object. However, any accesses of its fields are passed back to the original object. Serialization itself does not 'know' how to encode information that enables Remoting to create that proxy object. This is accomplished through the Remoting service using a Surrogate for that Remote-by-ref object. Note that in a graph of objects, some may be specified as Remote-by-val whilst others are specified as Remote-by-ref. As soon as Serialization encounters a Remote-by-ref object, it does not walk any subtree that object may have.

66 Serialization Transacted Persistence
Salesman Customer Order 2 Order 3 Order 1 The customer order process, represented in the graph, is under transactional control Serialization is complicated process Transacted Persistence provides its own formatters and serializers, which would layer on the basic serialization service Consider a very simple, and imaginary, Sales Order Processing System. A Salesman gathers orders at a Customer site. Later, these are fed into the company computer, which creates objects in memory, representing the situation, as shown in the diagram: This shows a graph of objects, representing a Customer, linked to a Salesman, and to three Orders.   The objects have been created by processing the Salesman's orders, connecting with company databases to check Customer details (billing address, delivery address, credit limit, discount levels, etc), similarly to check stock details (numberof items in stock, price, weights for transportation, etc). The result is to dispatch these orders to the shipping department, with billing information to the Accounts department, etc. All of this processing has been done under transactional control, with all that entails – locks held on database records to ensure isolation, two-phase commit protocol across multiple resource managers, write-ahead logging to ensure atomicity and recoverability, etc, etc. The fields of the objects have been populated with values held in various company databases. For example, all fields of the Salesman object may come from one record in the company's Salesman database. Of course, as the orders are processed, the system may update a TotalOrderValue field of that object, to reflect his monthly commission payment – and this information must be saved when the transaction completes. On the other hand, the Customer object may derive from several database tables – one for Customers, plus another for Addresses. So, populating the Customer object may involve extracting various columns from a Customer row, plus various colums from an Address row, into a buffer, which is then Deserialized into the object. Conversely, when the transaction completes, serialization of the object graph may be a complex process – selecting some fields of an object to update certain columns of a database table row, with other fields sent to a different destination. Some fields may even be copied twice, if the database schema has been denormalized for performance reasons. Moreover, the backing databases may not all be from the same vendor – for example, a mixture of SQL Server, Oracle, and legacy C-ISAM. The system must also be sure not to construct two instances of the same Customer in memory – that's to say, two copies of the object representing that particular customer. Allowing this to happen blows apart the guarantees required for Enterprise transactions, opening the field to lost updates, database inconsistencies, etc, etc. Similarly, when a transaction commits, the object graph must be either destroyed, or at least marked 'stale' to safeguard against multiple conflicting versions of the truth.

67 Serialization Basic Serialization
A Type is NOT Serializable unless Type is specifically marked as Serializable The Serializable Attribute The Non-Serializable Attribute [Serializable] public class MyClass {} Class authors need to be aware of serialization. The serialization services assume that a type is NOT Serializable unless type is specifically marked as Serializable. In the most simple case marking a class as Serializable is the all the class author will have to do. For slightly more complex classes with state that is invalid to serialize, we provide support for marking those fields and properties as transient. For the handful of classes that need to participate in their own serialization an Deserialization we provide an ISerializable interface. A class must be marked with the Serializable bit to be Serialized. An exception is thrown during serialization if the bit is not set of any class involved in the graph being serialized. In C#, this bit is set with a reserved custom attribute [Serializable] public class MyClass {} Classes with this addribute have all fields (even private ones) serialized. There are fields and properties on some types that it does not make since to serialize. Either for performance or correctness reasons the class author needs to tell the serialization service to "skip" these members. This is done by using the NotSerialized custom attribute. If the NotSerialized attribute is set the class author is saying this field or property within a class should not be serialized. In C# this bit is set with the transient keyword [Serializable] public class MyClass { [NotSerialized] int _cashSize; } [Serializable] public class MyClass { [NotSerialized] int _cashSize; }

68 Serialization Customize Serialization
Implementing ISerializable interface IDeserializationEventListener Custom Formatters Developers may want a way to customize exactly how data from a given object is serialized.   For that, the developer should implement the ISerializable interface on the given object. This may be useful for example when some of the data associated with your object may not be valid after deserialization (pointers, hashcodes, etc.) or when you want to create some data (through calculations or some other means) that allows you to reconstruct the full state of the object during deserialization. Implementing ISerializable involves implementing the GetObjectData method on your object and adding a constructor that takes a SerializationInfo and a StreamingContext as shown below.

69 Serialization ISerializable Interface
Customize the serialization process If a class implements ISerializable, that interface will always be called in preference to default serialization. The ISerializable interface is only contains one method: If a class author wishes to take special action when objects of that class are serialized and deserialized, he can choose to implement the ISerializable interface. This allows full control. For example, the author may define his own, custom SerializationInfo, to describe parts of the object, or synthesized fields that capture the object state for serialization. If a class implements ISerializable, that interface will always be called in preference to default serialization. The ISerializable interface is only contains one method: void GetObjectData (SerializationInfo info, StreamingContext context); And an implied constructor that may be private. private <TypeName> (SerializationInfo info, StreamingContext) An important note on deserialization is that we return the fields in the same order in which they are returned from Reflection. Reflection makes no guarantee that it will follow metadata ordering. void GetObjectData (SerializationInfo info, StreamingContext context); And an implied constructor that may be private. private <TypeName> (SerializationInfo info, StreamingContext)

70 Serialization IDeserializationEventListener
If an object implements IDeserializationEventListener, the serialization infrastructure will call that class‘ OnDeserialization method as soon as the entire graph has been deserialized and all fix-ups completed Provide a reasonable opportunity for objects that need to do fix-ups based on the state of their children

71 Serialization Custom Formatter
Implementing IFormatter Interface: public interface IFormatter: { //Properties SerializationBinder Binder { get; set; } StreamingContext Context { get; set; } ISurrogateSelector SurrogateSelector { get; set; } //Methods object Deserialize(Stream serializationStream); void Serialize(Stream serializationStream, object graph); } As seen a few times before, the Formatters are the classes that actualy format the information in the SerializationInfo into something that can be written to a stream. The Runtime provides two such formatters, the BinaryFormatter, and the SOAPFormatter. Since formatters are pluggable, developers can build their own if need be. The basic picture is as follows: The IFormatter interface must be implemented by a developer wishing to write their own formatter. The interface is simple and consists of two methods and three properties:

72 Conclusion Types' metadata can be explored with Reflection
Reflection provides dynamic type system The Federated Services Model is one of the core concepts for designing .NET applications in Internet Key .NET Remoting scenarios are: Web Services Anywhere CLR Object Remoting Serialization is the process of converting an object, or a connected graph of objects, stored within computer memory, into a linear sequence of bytes

73 Resources .NET Framework SDK


Download ppt ".NET Framework Advanced Topics"

Similar presentations


Ads by Google