Assemblies:
-Whenever a project is compiled it generates an output file known as Assembly. The name of an assembly will be the same as the project name from which it was created.
-An assembly file can have an extension of either exe or dll.
exe: executable dll: dynamic link library
-.Exe assemblies are in-process components that were capable of running on their own as well as provide the support for others to execute. When we use project templates like Windows Forms, WCF, Console Applications & Windows Services they generate an exe assembly when compiled.
-All assemblies are out-process components that were not capable of running on their own they can only support others to execute. Project templates like Class & Control Library will generate a dll assembly when compiled.
-Assemblies are of 2 types:
-Private Assemblies
-Shared Assemblies
Private Assemblies:
-By default every assembly is private, if reference of these assemblies was added to any project, a copy of the assembly is created and given to the project, so each project maintains a private copy of the assembly.
Creating a Private Assembly:
-Open a new project of type "Class Library" & name it as "PAssembly", which will by default come with a class as Class1.
Note: a class library is a collection of types like classes, interfaces, structures, etc., but cannot be executed, can only be consumed as they were dll's.
-Now under the class write following code:
public string SayHello()
{
return "Hello from private assembly";
}
-To compile the project open Solution Explorer, right-click on the project and select "Build" which will generate an assembly as PAssembly.dll.
Note: We can find the path of the assembly which was created in the output window present at bottom of the studio after the build.
Consuming the Private Assembly:
-Open a new project of type Windows, name it as "TestPAssembly", place a button on Form & set the text as "Call SayHello of PAssembly".
-Now add the reference of PAssembly.dll from its physical location & write the following code under click of button:
PAssembly.Class1 obj = new PAssembly.Class1();
MessageBox.Show(obj.SayHello());
-Run the project to test it, then go and verify under bin/debug folder of the current project where we can find a copy of PAssembly.dll as it was private.
Note: The advantage of a private assembly is faster execution as it was in the local folder, where as the drawback was multiple copies get created when multiple projects add the reference to consuming it.
Shared Assemblies:
-An assembly that sits under the GAC (Global Assembly Cache) to provide resources for multiple applications was known as a shared assembly.
-If an assembly was shared multiple copies will not be created even if being consumed by multiple projects, only a single copy under GAC serves all the projects.
-GAC was a special folder under the OS:
<drive>:\Windows\assembly <- GAC Folder
-Note: All the BCL were Shared dll Assemblies, so we can find them under GAC.
-What assemblies can be copied into GAC ?
Ans: We can copy only strong-named assemblies into GAC.
-What is a Strong Named Assembly ?
Ans: An assembly which has 3 attributes Name, Version & PublicKeyToken value were known as Strong Named Assemblies.
1. Name: it was the name of an assembly used for identification. Every assembly by default has name. eg: PAssembly
2. Version: every software has versions to it, for discriminating changes that have been made from time to time. As an assembly is also a software component it will maintain versions, whenever the assembly is created it has a default version for it i.e. 1.0.0.0, which can be changed when required.
3. Public Key Token: as GAC contains multiple assemblies in it, to identify each assembly it will maintain a key value for the assembly known as public key token, which should be generated by us & associate with an assembly to make it Strong Named.
-How to generate a Public Key Token ?
Ans: To generate a Public Key Token value we were provided with a tool, Strong Name Utility, which is a command line tool that should be used from VS command prompt as following:
sn -k <file name>
eg: sn -k Key.snk
-The above statement generates a key value & writes it into the file "Key.snk".
Note: use either sn or snk extension for key files.
Creating a Shared Assembly:
Step 1: Generate a key file. Open VS command prompt, go into your folder and generate a key file as following:
C:\CSharp> sn -k key.snk
Step 2: Create a project & associate the key file to it before compilation so that the assembly which is generated will be Strong Named.
-Open a new project of type Class Library & name it as "SAssembly".
-Under the class Class1 write following code:
public string SayHello()
{
return "Hello from shared assembly 1.0.0.0";
}
-To associate the key file we have generated with project, open project properties window, select Signing tab on LHS, which displays a CheckBox as "Sign the Assembly" select it, in the ComboBox below select browse, select the key.snk file from its physical location which adds the file under solution explorer, then compile the project using "Build" option that will generate SAssembly.dll which is Strong Named.
Step 3: Copying the Assembly into GAC.
-To copy the assembly into GAC .Net provides an utility known as "gacutil" which is a command-line tool that has to be used as follows:
gacutil -i | -u <assembly name>
-i Install
-u Uninstall
-Open VS command prompt, go into the location where SAssembly.dll was present and write the following:
C:\CSharp\SAssembly\SAssembly\bin\Debug> gacutil -i SAssembly.dll
Step 4: Testing the Shared Assembly:
-Open a new project of type Windows & name it as "TestSAssembly", place a button on form & set the text as "Call SayHello of SAssembly 1.0.0.0".
-Add reference of SAssembly.dll from its physical location & write following code under button click:
SAssembly.Class1 obj = new SAssembly.Class1();
MessageBox.Show(obj.SayHello());
-Run the project, test it and verify under bin/debug folder of the current project where we will not find any copy of SAssembly.dll as it was shared.
Note: when a shared assembly is used in multiple applications there will not be multiple copies of the assembly, whereas it's not faster when compared with private assembly.
Assembly Attributes:
-An assembly is associated with a set of attributes that describes the general info of an assembly like Title, Company, Description, Version, etc.
-These attributes will be under AssemblyInfo.cs file of each project. To view them expand the properties node under the project in Solution Explorer where we find AssemblyInfo.cs file.
Note: We can change the values of any attribute as per our requirements.
-In the bottom of the file we find an attribute version which is a combination of 4 values:
-Major Version
-Minor Version
-Build Number
-Revision
-The default version of every assembly is 1.0.0.0, to change version no. we follow the below guidelines:
-Change revision no when modifications were made to existing members of types in an assembly.
-Change build no when new members were added to existing types in an assembly.
-Change minor versions when modifications were made to existing types in an assembly.
-Change the major version when new types were added in an assembly.
Checking the process of changing version no's:
-Open SAssembly project we created previously & change the code under SayHello method as below:
return "Hello from new shared assembly 1.0.0.1";
-Now open AssemblyInfo.cs file and change the AssemblyVersion & AssemblyFileVersion attributes to 1.0.0.1.
-Re-build the project and add the new version of SAssembly also into GAC using gacutil tool.
Note: GAC allows placing of multiple versions of an assembly in it & provides different app using different versions of the assembly to execute correctly using their required version.
-Now open the GAC folder where we find 2 versions of SAssembly i.e. 1.0.0.0 & 1.0.0.1
-After placing multiple versions of an assembly under GAC we can develop applications in such a way where a different application uses a different version of the assembly and still execute correctly what we call as side by side execution which was not possible under tradition COM technologies.
-To test this open a new project of type Windows and name it as TestSAssemblyNew, place a button on the form and set the text as "Call SayHello of SAssembly 1.0.0.1".
-Add reference of 1.0.0.1 version of SAssembly from its physical location and write the following code under button click:
SAssembly.Class1 obj = new SAssembly.Class1();
MessageBox.Show(obj.SayHello());
To check side by side execution of projects run the exe files of TestSAssembly & TestSAssemblyNew projects at the same time, where each project will use it's required version of SAssembly & execute, as following:
Multi-Module Assemblies (2.0):
.netmodule
Imports System
Namespace MyVBNSP
Public Class VBTest
Public Function VBMethod() As String
Return "Hello from Visual Basic"
End Function
End Class
End Namespace
using System;
namespace MyCSNSP
{
public class CSharpTest
{
public string CSMethod()
{
return "Hello from C Sharp";
}
}
}
Compiling Sub-Modules:
vbc /target:module <vb file name>
csc /target:module <cs file name>
Compiling Main-Module:
vbc [/target:library] /addmodule:<list of sub modules> <vb file name>
csc [/target:library] /addmodule:<list of sub modules> <cs file name>
Making VBTest as a Sub-Module:
C:\CSharp> vbc /target:module VBTest.vb
Making CShartTest as a Main-Module:
C:\CSharp> csc /target:library /addmodule:VBTest.netmodule CSharpTest.cs
Consuming Multi-Module assembly:
-Open a new project of type windows and name it as TestMulti, place 2 buttons on the form and set the text as "Call CS Test" & "Call VB Test".
-Add reference of the CSharpTest.dll what we generated above from its physical location .
Under Call CS Test Button:
MyCSNSP.CSharpTest obj = new MyCSNSP.CSharpTest();
MessageBox.Show(obj.CSMethod());
Under Call VB Test Button:
MyVBNSP.VBTest obj = new MyVBNSP.VBTest();
MessageBox.Show(obj.VBMethod());
Globalization & Localization using Satellite Assemblies
MyRes.resx:
Name Value
L1 User Name
L2 Password
B1 Login
B2 Logout
MyRes.hi-IN.resx:
Name Value
L1 उपयोगकर्ता नाम
L2 पासवर्ड
B1 साइन इन
B2 साइन आउट
MyRes.te-IN.resx:
Name Value
L1 యూజర్పేరు
L2 పాస్వర్డు
B1 సైన్ ఇన్
B2 సైన్ ఔట్
System.Globalization
CultureInfo(string cultureflag)
System.Resources
ResourceManager(string basename,
Assembly assembly)
-In place of Assembly, we need to give the currentlly executing assembly information to get that use the Method GetExecutingAssembly() under Assembly class of System.Reflection namespace.
using System.Reflection;
using System.Resources;
using System.Globalization;
Declarations:
CultureInfo ci;
ResourceManager rm;
Under Form Load:
rm = new ResourceManager("MultiLang.MyRes", Assembly.GetExecutingAssembly());
private void GetValues()
{
label1.Text = rm.GetString("L1", ci);
label2.Text = rm.GetString("L2", ci);
button1.Text = rm.GetString("B1", ci);
button2.Text = rm.GetString("B2", ci);
}
Under English Link Label:
ci = new CultureInfo("en-US");
GetValues();
Under Hindi Link Label:
ci = new CultureInfo("hi-IN");
GetValues();
Under Telugu Link Label:
ci = new CultureInfo("te-IN");
GetValues();
Note: Now go and verify under the debug folder of the current project where we find a separate folder created for each resource file (except English) & in the folder we find the satellite assembly which got created.
-An Assembly internally contains following things in it:
-Manifest Info
-Type Metadata
-IL Code
-Resource Info
Manifest Info: It contains info about the attributes that are associated with an assembly like Title, Description, Company, Version, etc.,
Type Metadata: It contains info about all the types under assembly like Namespaces, Classes, their members (only signature), Structures, Interfaces, etc. It describes only about contents of assembly, so an assembly can be called as a self-describing unit of execution which describes itself to the execution environment with the help of its metadata.
Note: When we add a reference to an assembly VS will read the information of assembly from its type metadata only using reflection.
-A reflection is an approach of dynamically recognizing the contents of an assembly.
IL Code: This was the language instructions we have defined using .net lang's which can be understood only by the CLR and required only while execution of application.
Resource Info: this is going to contain the info which was associated with the resource files which was only optional.
COM: Component Object Model
-It's a specification prescribed by Microsoft which advices never build software as a monolithic unit(single), in spite it suggests the building of software by dividing into smaller components (libraries) & then integrate as software that gives below features:
i) Software maintenance becomes easier.
ii) The reusability of components under multiple apps is possible.
iii) Language Independency.
-In spite of the features it has, it suffers from a few criticisms also:
i) Platform dependency where COM works only on windows.
ii) COM components (dll or exe) have to be first registered under the OS registry to consume on a machine.
iii) Versioning problem or dll Hell.
Note: COM components were nothing but libraries similar to assemblies in .Net.
-To overcome the problems with COM components, in .Net Microsoft replaced them with Assemblies which are Platform Independent, don't require any OS registration and also solves versioning problem's.
COM Interoperability:
-After replacing COM libraries with .Net assemblies Microsoft has given flexibility to the industry i.e. consuming of COM libraries under .Net application development and .Net assemblies under COM app development known as COM Interoperability.
-A COM component can be consumed under a .Net application by converting it into RCW (Runtime Callable Wrapper) which exposes COM interfaces as .Net interfaces to .Net applications.
-CCW (COM Callable Wrapper) is opposite of RCW that exposes .Net interfaces as COM interfaces to a COM applications.
Developing a COM Component:
-COM Components can be developed using various languages like classical VB, C++ & VCPP.
-To develop a COM Component in Classical VB goto Start Menu -> Programs -> Microsoft Visual Studio 6.0 -> Microsoft Visual Basic 6.0 -> click on it which shows "New Project" window -> select ActiveX Dll (Class Library in .Net) project template -> click on open which displays the code window.
-Goto View Menu -> select "Project Explorer" which launches the explorer on RHS -> right click on the node Project1 -> select properties which open a window -> under that change the "Project Name" as CSharp1 -> click Ok.
-Now right click on Class1 node -> select properties -> change the name as "Test".
-Now in code window write the following:
Public Function SayHello() As String
SayHello = "Hello from COM"
End Function
Note: classical VB lang doesn't support return statement so the value which has to be returned should be assigned to name of the function which will return the value.
-Go to File Menu -> select Save Project -> specify a location to save the project.
eg: C:\CSharp1\VB
-Go to File Menu -> select Make 'CSharp11.dll', which will compile, generate a dll and registers it under windows registry because COM Components were not functional unless they were registered under windows registry.
-Close the Studio.
Registering Com components under OS registry:
-We can also manually register com components under windows registry, using the following command from command prompt:
syntax: regsvr32 <name of com dll>
eg: C:\CSharp6\VB> regsvr32 CSharp6.dll
Note: we don't require it right now because VS has already registered our component.
Consuming COM Components from .Net App's:
-If we want to consume a COM Component from .Net Applications first it should be converted into RCW which can be done in 2 ways:
-Using Visual Studio.Net
-Using tlbimp utility
Using Visual Studio.Net:
-Open a new .Net project of type Windows & name it is as TestCom1, place a button on the form & set Text as "Call SayHello of COM".
-Now open "Add Reference" window, select COM tab & under it we can find the Component CSharp1 we have created, select it and write the following code under the click of a button:
CSharp1.TestClass obj = new CSharp1.TestClass();
MessageBox.Show(obj.SayHello());
-Run the project, test it & then go into debug folder of the current project where we can find the RCW created by VS as "Interop.CSharp1.dll".
-The above process is simple & easy but the RCW created here is private which maintains multiple copies if used under multiple projects.
Using tlbimp Utility:
-VS is capable of generating RCW of type private only whereas tlbimp is capable of generating both private & shared RCW's.
-To create an RCW Or CCW we were provided with 2 command-line utilities:
1. tlbimp (Type Library Importer): for converting a COM component into RCW
2. tlbexp (Type Library Exporter): for converting a .net assembly into CCW
-These were command-line utilities which should be used from VS Command Prompt as following:
tlbimp <name of com dll> /out: <name of .net dll> [/keyfile: <name of key file>]
Creating a Private RCW:
C:\CSharp1\VB> tlbimp CSharp6.dll /out:ComToNetP.dll
Creating a Shared RCW:
Step 1: Generate a key file
C:\CSharp1\VB> sn -k Key.snk
Step 2: Convert to Shared RCW
C:\CSharp1\VB> tlbimp CSharp6.dll /out:ComToNetS.dll /keyfile: Key.snk
Step 3: Add the RCW to GAC
C:\CSharp1\VB> gacutil -i ComToNetS.dll
-Now add to more buttons on our previous project TestCom1 with the same Text, add the reference of both the RCW's we have created (ComToNetP.dll & ComToNetS.dll) from their physical location, then write the following code under them:
Under Second Button:
ComToNetP.TestClass obj = new ComToNetP.TestClass();
MessageBox.Show(obj.SayHello());
Under Third Button:
ComToNetS.TestClass obj = new ComToNetS.TestClass();
MessageBox.Show(obj.SayHello());
tlbexp is a tool that converts a .Net assembly into CCW, this is opposite to tlbimp.
tlbexp <name of .net dll> /out:<name of com dll>
Note: after creating CCW it cannot be used directly under any system as it was a COM component, it first requires registration on windows OS which has to be done using regsvr32 statement we discussed above.
No comments:
Post a Comment