+ All Categories
Home > Documents > Versioning

Versioning

Date post: 07-Sep-2014
Category:
Upload: karthika-parthasarathy
View: 249 times
Download: 0 times
Share this document with a friend
Description:
 
14
VERSIONING: The C# language is designed such that versioning between base and derived classes in different libraries can evolve and maintain backwards compatibility. This means, for example, that the introduction of a new member in a base class with the same name as a member in a derived class is not an error. It also means that a class must explicitly state whether a method is intended to override an inherited method, or whether a method is a new method that simply hides a similarly named inherited method. In C#, methods are by default, not virtual. To make a method virtual, the virtual modifier has to be used in the method declaration of the base class. The derived class can then override the base virtual method by using the override keyword or hide the virtual method in the base class by using the new keyword. If neither the override keyword nor the new keyword is specified, the compiler will issue a warning and the method in the derived class will hide the method in the base class. The following example shows these concepts in action. Example // versioning.cs // CS0114 expected public class MyBase { public virtual string Meth1() { return "MyBase-Meth1"; } public virtual string Meth2() { return "MyBase-Meth2"; } public virtual string Meth3() { return "MyBase-Meth3"; } }
Transcript
Page 1: Versioning

VERSIONING:

The C# language is designed such that versioning between base and derived classes in different libraries can evolve and maintain backwards compatibility. This means, for example, that the introduction of a new member in a base class with the same name as a member in a derived class is not an error. It also means that a class must explicitly state whether a method is intended to override an inherited method, or whether a method is a new method that simply hides a similarly named inherited method.

In C#, methods are by default, not virtual. To make a method virtual, the virtual modifier has to be used in the method declaration of the base class. The derived class can then override the base virtual method by using the override keyword or hide the virtual method in the base class by using the new keyword. If neither the override keyword nor the new keyword is specified, the compiler will issue a warning and the method in the derived class will hide the method in the base class. The following example shows these concepts in action.

Example

// versioning.cs// CS0114 expectedpublic class MyBase { public virtual string Meth1() { return "MyBase-Meth1"; } public virtual string Meth2() { return "MyBase-Meth2"; } public virtual string Meth3() { return "MyBase-Meth3"; }}

class MyDerived : MyBase { // Overrides the virtual method Meth1 using the override keyword: public override string Meth1() { return "MyDerived-Meth1"; } // Explicitly hide the virtual method Meth2 using the new // keyword: public new string Meth2() { return "MyDerived-Meth2"; } // Because no keyword is specified in the following declaration // a warning will be issued to alert the programmer that

Page 2: Versioning

// the method hides the inherited member MyBase.Meth3(): public string Meth3() { return "MyDerived-Meth3"; }

public static void Main() { MyDerived mD = new MyDerived(); MyBase mB = (MyBase) mD;

System.Console.WriteLine(mB.Meth1()); System.Console.WriteLine(mB.Meth2()); System.Console.WriteLine(mB.Meth3()); }}

Output

MyDerived-Meth1MyBase-Meth2MyBase-Meth3

Code Discussion

Hiding a base class member from a derived class isn't an error in C#. This feature enables you to make changes in the base class without breaking other libraries that inherit this base class. For example, at some point you could have the following classes:

class Base {}class Derived: Base{ public void F() {}}

At some later point, the base class could evolve to add a void method F() as follows:

class Base { public void F() {}}class Derived: Base{ public void F() {}}

Thus, in C#, both the base and derived classes can evolve freely and maintain binary compatibility.

Page 3: Versioning

ATTRIBUTES:

Attributes provide a powerful method of associating declarative information with C# code (types, methods, properties, and so forth). Once associated with a program entity, the attribute can be queried at run time and used in any number of ways.

Example usage of attributes includes:

Associating help documentation with program entities (through a Help attribute). Associating value editors to a specific type in a GUI framework (through a

ValueEditor attribute).

In addition to a complete example, this tutorial includes the following topics:

Declaring an Attribute Class

The first thing you need to be able to do is declare an attribute.

Using an Attribute Class

Once the attribute has been created, you then associate the attribute with a particular program element.

Accessing Attributes Through Reflection

Once the attribute has been associated with a program element, you use reflection to query its existence and its value.

Declaring an Attribute Class

Declaring an attribute in C# is simple — it takes the form of a class declaration that inherits from System.Attribute and has been marked with the AttributeUsage attribute as shown below:

using System;[AttributeUsage(AttributeTargets.All)]public class HelpAttribute : System.Attribute { public readonly string Url;

public string Topic // Topic is a named parameter { get { return topic; } set {

Page 4: Versioning

topic = value; } }

public HelpAttribute(string url) // url is a positional parameter { this.Url = url; }

private string topic;}

Code Discussion

The attribute AttributeUsage specifies the language elements to which the attribute can be applied.

Attributes classes are public classes derived from System.Attribute that have at least one public constructor.

Attribute classes have two types of parameters: Positional parameters must be specified every time the attribute is used.

Positional parameters are specified as constructor arguments to the attribute class. In the example above, url is a positional parameter.

Named parameters are optional. If they are specified when the attribute is used, the name of the parameter must be used. Named parameters are defined by having a nonstatic field or property. In the example above, Topic is a named parameter.

Attribute parameters are restricted to constant values of the following types: Simple types (bool, byte, char, short, int, long, float, and double) string System.Type enums object (The argument to an attribute parameter of type object must be a

constant value of one of the above types.) One-dimensional arrays of any of the above types

Parameters for the AttributeUsage Attribute

The attribute AttributeUsage provides the underlying mechanism by which attributes are declared.

AttributeUsage has one positional parameter:

AllowOn, which specifies the program elements that the attribute can be assigned to (class, method, property, parameter, and so on). Valid values for this parameter can be found in the System.Attributes.AttributeTargets enumeration in the .NET Framework. The default value for this parameter is all program elements (AttributeElements.All).

Page 5: Versioning

AttributeUsage has one named parameter:

AllowMultiple, a Boolean value that indicates whether multiple attributes can be specified for one program element. The default value for this parameter is False.

Using an Attribute Class

Here's a simple example of using the attribute declared in the previous section:

[HelpAttribute("http://localhost/MyClassInfo")]class MyClass {}

In this example, the HelpAttribute attribute is associated with MyClass.

Note   By convention, all attribute names end with the word "Attribute" to distinguish them from other items in the .NET Framework. However, you do not need to specify the attribute suffix when using attributes in code. For example, you can specify HelpAttribute as follows:[Help("http://localhost/MyClassInfo")] // [Help] == [HelpAttribute]class MyClass {}

Accessing Attributes Through Reflection

Once attributes have been associated with program elements, reflection can be used to query their existence and values. The main reflection methods to query attributes are contained in the System.Reflection.MemberInfo class (GetCustomAttributes family of methods). The following example demonstrates the basic way of using reflection to get access to attributes:

class MainClass { public static void Main() { System.Reflection.MemberInfo info = typeof(MyClass); object[] attributes = info.GetCustomAttributes(true); for (int i = 0; i < attributes.Length; i ++) { System.Console.WriteLine(attributes[i]); } } }

Page 6: Versioning

Example

The following is a complete example where all pieces are brought together.

// AttributesTutorial.cs// This example shows the use of class and method attributes.

using System;using System.Reflection;using System.Collections;

// The IsTested class is a user-defined custom attribute class.// It can be applied to any declaration including// - types (struct, class, enum, delegate)// - members (methods, fields, events, properties, indexers)// It is used with no arguments.public class IsTestedAttribute : Attribute{ public override string ToString() { return "Is Tested"; }}

// The AuthorAttribute class is a user-defined attribute class.// It can be applied to classes and struct declarations only.// It takes one unnamed string argument (the author's name).// It has one optional named argument Version, which is of type int.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]public class AuthorAttribute : Attribute{ // This constructor specifies the unnamed arguments to the attribute class. public AuthorAttribute(string name) { this.name = name; this.version = 0; }

// This property is readonly (it has no set accessor) // so it cannot be used as a named argument to this attribute. public string Name { get { return name; } }

// This property is read-write (it has a set accessor) // so it can be used as a named argument when using this // class as an attribute class. public int Version { get {

Page 7: Versioning

return version; } set { version = value; } }

public override string ToString() { string value = "Author : " + Name; if (version != 0) { value += " Version : " + Version.ToString(); } return value; }

private string name; private int version;}

// Here you attach the AuthorAttribute user-defined custom attribute to // the Account class. The unnamed string argument is passed to the // AuthorAttribute class's constructor when creating the attributes.[Author("Joe Programmer")]class Account{ // Attach the IsTestedAttribute custom attribute to this method. [IsTested] public void AddOrder(Order orderToAdd) { orders.Add(orderToAdd); }

private ArrayList orders = new ArrayList();}

// Attach the AuthorAttribute and IsTestedAttribute custom attributes // to this class.// Note the use of the 'Version' named argument to the AuthorAttribute.[Author("Jane Programmer", Version = 2), IsTested()]class Order{ // add stuff here ...}

class MainClass{ private static bool IsMemberTested(MemberInfo member) { foreach (object attribute in member.GetCustomAttributes(true)) { if (attribute is IsTestedAttribute) { return true; }

Page 8: Versioning

} return false; }

private static void DumpAttributes(MemberInfo member) { Console.WriteLine("Attributes for : " + member.Name); foreach (object attribute in member.GetCustomAttributes(true)) { Console.WriteLine(attribute); } }

public static void Main() { // display attributes for Account class DumpAttributes(typeof(Account));

// display list of tested members foreach (MethodInfo method in (typeof(Account)).GetMethods()) { if (IsMemberTested(method)) { Console.WriteLine("Member {0} is tested!", method.Name); } else { Console.WriteLine("Member {0} is NOT tested!", method.Name); } } Console.WriteLine();

// display attributes for Order class DumpAttributes(typeof(Order));

// display attributes for methods on the Order class foreach (MethodInfo method in (typeof(Order)).GetMethods()) { if (IsMemberTested(method)) { Console.WriteLine("Member {0} is tested!", method.Name); } else { Console.WriteLine("Member {0} is NOT tested!", method.Name); } } Console.WriteLine(); }}

Output

Attributes for : Account

Page 9: Versioning

Author : Joe ProgrammerMember GetHashCode is NOT tested!Member Equals is NOT tested!Member ToString is NOT tested!Member AddOrder is tested!Member GetType is NOT tested!

Attributes for : OrderAuthor : Jane Programmer Version : 2Is TestedMember GetHashCode is NOT tested!Member Equals is NOT tested!Member ToString is NOT tested!Member GetType is NOT tested!

What is marshalling? Explain types of marshalling.

Marshaling is a process of transforming or serializing data from one application domain and exporting it to another application domain.

Two types of marshalling

Marshal by value: a copy of an object is created by the server and is passed and used by the client.

Marshal by reference: the client creates a proxy to access the object.

Source code:

Server part:

1. Create a Console Application named TicketServer.2. Add System.Runtime.Remoting as a reference to the project.3. Replace the existing code in Class.cs with the following code and build the project.

01 using System;02 using System.Runtime.Remoting;03 using System.Runtime.Remoting.Channels;04 using System.Runtime.Remoting.Channels.Tcp;05  06 class Program07 {08 static void Main(string[] args)09 {10 TicketServer();11 }12  13 static void TicketServer()14 {

Page 10: Versioning

15 Console.WriteLine("Ticket Server started...");16  17 TcpChannel tcpChannel = new TcpChannel(9998);18 ChannelServices.RegisterChannel(tcpChannel);19  20 Type commonInterfaceType = Type.GetType("MovieTicket");21  

22 RemotingConfiguration.RegisterWellKnownServiceType(commonInterfaceType,

23 "MovieTicketBooking", WellKnownObjectMode.SingleCall);24  25 System.Console.WriteLine("Press ENTER to quitnn");26 System.Console.ReadLine();27  28 }29  30 }31  32 public interface MovieTicketInterface33 {34 string GetTicketStatus(string stringToPrint);35 }36  37 public class MovieTicket : MarshalByRefObject, MovieTicketInterface38 {39 public string GetTicketStatus(string stringToPrint)40 {41 string returnStatus = "Ticket Confirmed";42 Console.WriteLine("Enquiry for {0}", stringToPrint);43 Console.WriteLine("Sending back status: {0}", returnStatus);44  45 return returnStatus;46 }47 }

Client side:

1. Create a Console Application named Client.2. Add System.Runtime.Remoting and Server.exe [See Note 1] as references to the project.3. Replace the existing code in Class.cs with the following code and build the project.

01 using System;02 using System.Runtime.Remoting;03 using System.Runtime.Remoting.Channels;04 using System.Runtime.Remoting.Channels.Tcp;05  

Page 11: Versioning

06 class MyClient07 {08 public static void Main()09 {10 TcpChannel tcpChannel = new TcpChannel();11 ChannelServices.RegisterChannel(tcpChannel);12  13 Type requiredType = typeof(MovieTicketInterface);14  

15 MovieTicketInterface remoteObject = (MovieTicketInterface)Activator.GetObject(requiredType,

16 "tcp://localhost:9998/MovieTicketBooking");17  18 Console.WriteLine(remoteObject.GetTicketStatus("Ticket No: 3344"));19 }20 }

Execution:

1. Execute Server.exe2. Execute Client.exe

You will see the appropriate messages on the client side and the remote side.

Note 1: If you are using Visual Studio 2003, you cannot add a reference to an exe file. Make a copy of Server.exe, rename it to Server.dll and this can be added as a reference in your client project.


Recommended