using .net classes in pb.ppt -...
TRANSCRIPT
6/5/2009
1
Using .NET classes in PowerBuilderPowerBuilder Developers are .NET Developers!
Donald D. [email protected]
Agenda
• Overview of .NET
• Overview of PB .NET
• Using .NET features in PowerBuilder
• Translating C# code snippet to PowerScript
• Consuming Web Services using .NET interop
6/5/2009
2
Overview of .NETA huge opportunity for PowerBuilder developers
Overview of .NET
A software platform for both desktop and Web• Development
– Object-oriented, event driven programming model– Unify desktop and Web application development
• Deployment– DLL hell– ClickOnce
• SmartClient
6/5/2009
3
Overview of .NET
A software platform for both desktop and Web• Common Language Runtime
– Garbage collection, security, versioning, etc
• A huge class library– XML, collections, many others
• Applications– Windows Forms– Web Forms– Web services– WPF (Windows Presentation Foundation)– Silverlight (Windows Presentation Foundation/Everywhere)
http://silverlight.net/
Overview of .NET
6/5/2009
4
Overview of PB .NETRAD tool for developing data-centric .NET applications
Overview of PB .NET
PB .NETCompiler
PowerBuilder .NET Runtime
.NETApplication
Generates
References
PBL FilesSource code
The architecture of PowerBuilder .NET compiler
6/5/2009
5
Overview of PB .NET
PowerBuilder .NET Runtime
PB .NET Application
PB Native DLLs
The architecture of PowerBuilder .NET applications
.NET Framework
3rd Party .NETAssemblies
Windows 32 Platform
.NET interop
Overview of PB .NET
What can you do with PB .NET• Deploy an application
– As a .NET Windows Forms/SmartClient application– As a .NET Web Forms application
• Deploy an NVO – As a .NET class– As a .NET Web service
• .NET interop
6/5/2009
6
Overview of PB .NET
Architecture:.NET Web Forms Applications
DB Drivers
DataWindow .NETWebForm Control
PowerBuilder Web Form Application
PowerBuilder .NET Runtime
PowerBuilder ApplicationCompiles to
PB Native DLLs (without PBVM)
Sybase.PowerBuilder.Core.DLL
Sybase.PowerBuilder.Interop.DLL
Sybase.PowerBuilder.Common.DLL
Sybase.PowerBuilder.Web.DLL
PBSHR.DLL
PBDWM.DLL
Overview of PB .NET
Architecture:.NET Windows Forms Applications
DB Drivers
DataWindow .NETWindows Form Control
PowerBuilder .NET Runtime
PowerBuilder ApplicationCompiles to
PB Native DLLs (without PBVM)
Application configApplication manifest
Sybase.PowerBuilder.Core.DLL
Sybase.PowerBuilder.Interop.DLL
Sybase.PowerBuilder.Common.DLL
Sybase.PowerBuilder.Win.DLL
PBSHR.DLL
PBDWM.DLL
PowerBuilder WindowsForm Application
6/5/2009
7
Overview of PB .NET
DataWindow .NET
NVO ASP.NETWeb Service PBLs with NVOs
PowerBuilder .NET RuntimePB Native DLLs (without PBVM)
Architecture:.NET Web Services
Sybase.PowerBuilder.Interop.DLL
Sybase.PowerBuilder.Common.DLL
Sybase.PowerBuilder.Web.DLL
Sybase.PowerBuilder.Core.DLL
PBSHR.DLL
DB Drivers
PBDWM.DLL
Compiles to
Overview of PB .NET
DataWindow .NET
NVO .NET Assembly PBLs with NVOs
PowerBuilder .NET RuntimePB Native DLLs (without PBVM)
Architecture:.NET Assemblies
Sybase.PowerBuilder.Interop.DLL
Sybase.PowerBuilder.Common.DLL
Sybase.PowerBuilder.Win.DLL
Sybase.PowerBuilder.Core.DLL
PBSHR.DLL
DB Drivers
PBDWM.DLL
Compiles to
6/5/2009
8
.NET InteroperationConsuming .NET features in PowerBuilder
.NET Interoperation
.NET features that can be consumed in PowerBuilder 11
• Non-generic classes– Instance members– Static members (new enhancement)– Parameterized constructors (new enhancement)
• Non-generic interfaces• Enums• Arrays• Exceptions
6/5/2009
9
Import .NET Assemblies
Import .NET Assemblies
6/5/2009
10
.NET Code Block
.NET code block
Type mapping
.NET types PowerBuilder typesBool BooleanByte Byte
Char Char
DateTime DateTimeDecimal Decimal
Double Double
Float RealInt16 Integer
Int32 Long
Int64 LonglongSbyte Sbyte
String String
Uint16 UnsignedintegerUint32 Unsignedlong
Uint64 Unsignedlonglong
6/5/2009
11
Using .NET classes
Non-generic classes• Instance members
– Methods, fields, properties
• Static members– Methods, fields, properties
• Parameterized constructors
Using .NET classes
Instance members• Methods, fields, properties• Just like accessing PB instance members
system.xml.xmlTextReader readerreader = create system.xml.XmlTextReader(path)…if reader.hasAttributes thenFor i = 0 To reader.AttributeCount - 1reader.MoveToAttribute(i)lb_1.addItem(reader.Name + “: “ + reader.Value)
Nextreader.MoveToElement()
end if
6/5/2009
12
Using .NET classes
Static members• Methods, fields, properties• Accessing the members on the class.• Not available in Win32 targets
// Current is a static field of class HttpContextSystem.Web.HttpContext contextcontext = System.Web.HttpContext.Current
Using .NET classes
Parameterized constructors• Not available in Win32 targets
String pathPath = “d:\myfolder\foo.xml”
system.xml.xmlTextReader readerreader = create system.xml.XmlTextReader(path)
6/5/2009
13
Using .NET interfaces
An interface defines a contract• Interfaces don’t contain implementation.• Classes that implement the interface implement the contract.• No static members in interfaces
Just like using .NET classes.
Using .NET enums
Use qualified name
// PB enumerated itemBorderStyle stylestyle = StyleLowered!
// .NET enumSystem.Windows.Forms.BorderStyle stylestyles = System.Windows.Forms.BorderStyle.FixedSingle!
6/5/2009
14
Using .NET arrays
Three kinds of arrays• Single-dimensional arrays• Multidimensional arrays• Jagged arrays (array of arrays)
All .NET arrays are of type System.Array• All .NET arrays can be accessed using the System.Array class
By default, indices of .NET arrays starts from 0
Using Single-dimensional .NET Arrays
• Declare an array and assign the return value to it
.NET function of class Company: public string[] getEmployees(int department)
PowerScript code:int iString employees[]Employees = l_company.getEmployees(departmentId)For i = 1 to upperBound(employees)lb_1.addItem(employees[i])
next
6/5/2009
15
Using Multidimensional .NET Arrays
• Difference between .NET arrays and PB arrays– In .NET, the last dimension is the fastest-varying dimension– In PB, the first dimension is the fastest-varying dimension
// C# string[,] a = new string[2, 3] { { "a", "b", "c" }, { "d", "e", "f" } };// a[0,2] = “c”
// PBString s[2,3] = { "a", "b", "c", "d", "e", "f" }// s[1, 2] = “c”
“a” “b” “c”"d" "e" "f"
“a” “b” “c” "d" "e" "f"
Using Multidimensional .NET Arrays
• If the bounds information is known at compile-time
// PowerScript codestring sa[3,2] // 3 columns, 2 rowssa = a.getArray() // call the .NET function
string ss[]ss = sa
string strint ifor i = 1 to 6str += ss[i]
next
// The result of str is “abcdef”.
6/5/2009
16
Using multidimensional .NET arrays
• If the array bounds information is unknown at compile-time
.NET function of class Polygon: public int[,] GetVertices()
PowerScript code:int iSystem.Array pointspoints = l_triangle.getVertices()For i = points.getLowerBound(0) to points.getUpperBound(0)lb_1.addItem(string(points.getValue(i,0)) + “, “ +&
string(points.getValue(i,1)))next
Using Multidimensional .NET Arrays
• A .NET array can be assigned to a PB array if array bounds information is known at compile-time.
– Assigning multidimensional .NET arrays to/from PB arrays are costly.
– Using System.Array to access multidimensional arrays when performance is important.
• .NET arrays are accessible through the System.Array class regardless whether the array bounds information is known at compile-time.
6/5/2009
17
Creating a Multidimensional .NET Array
System.Int32 lengths[]System.Int32 lowerBounds[]
lowerBounds[1] = 0; lengths[1] = 4lowerBounds[2] = 0; lengths[2] = 5lowerBounds[3] = 0; lengths[3] = 6
System.Array arrarr = System.Array.CreateInstance([email protected](&"System.String"), lengths, lowerBounds)
Arr.setValue(200, 1, 2, 3) // arr[1,2,3] = 200 messagebox("arr[1,2,3]", string(arr.getValue(1,2,3)))
string pbarr[6, 5, 4]pbarr = arr
messagebox("pbarr[4,3,2]", pbarr[4,3,2])
Using Jagged .NET Arrays
.NET function: public int[][] getJaggedArray()PowerScript code:long i, j, kSystem.Array arr1, arr2arr1 = obj.getJaggedArray() // obj is a .NET objectfor i = arr1.getLowerBound(0) to arr1.getUpperBound(0)arr2 = arr1.getValue(i)for j = arr2.getLowerBound(0) to arr2.getUpperBound(0) k = arr2.getValue(j)…next
next
6/5/2009
18
Creating a Jagged .NET Array
System.@Type tt = [email protected]("System.Int32[]")System.Array mama = System.Array.CreateInstance(t, 4)
System.Array a1 = System.Array.CreateInstance(& [email protected]("System.Int32"), 5)
ma.SetValue(a1, 0)a1.SetValue(100, 0)
messagebox("ma[0][0]", string(a1.getValue(0)))
Exceptions
trysystem.xml.xpath.xpathDocument docdoc = create system.xml.xpath.XPathDocument(sle_1.text)
system.xml.xpath.XPathNavigator navnav = doc.CreateNavigator()
system.xml.xpath.XPathNodeIterator iteriter = nav.Select(sle_2.text) // might throw exception
do While iter.MoveNext()lb_1.AddItem(iter.Current.Value)
loopcatch (system.ArgumentException ae)messageBox("ArgumentException", ae.toString())
catch (System.Xml.XPath.XPathException xe)messageBox("XPathException", xe.toString())
end try
6/5/2009
19
Commonly Used .NET Classes
• System.Collections and System.Collections.Specialized– ArrayList, Hashtable, Queue, Stack, SortedList, StringDictionary
• System.Xml– XmlDocument, XmlElement
• System.IO and System.IO.Compression– Directory, File, GZipStream
• System.Net– WebClient, WebRequest, WebResponse, SmtpClient
• System.Text and System.Text.RegularExpressions– Regex
Commonly Used .NET Classes
• Class reference can be found here– http://msdn2.microsoft.com/en-us/library/aa388745.aspx
6/5/2009
20
Translating C# Code Snippet to PowerScript
• Use full-qualified type name– E.g. System.Collections.Hashtable
• Change C# syntax to PowerScript syntax– “new” to “create”
• Type mapping– Int32 => long, int16 => integer, and so on
• Separate variable declaration and assignment statements– In C#: WebClient client = new WebClient();
– In PowerScript:System.Net.WebClient clientclient = create System.Net.WebClient
Translating C# Code Snippet to PowerScript
// C# codeSortedList mySL = new SortedList(); mySL.Add("First", "Hello"); mySL.Add("Second", "World"); mySL.Add("Third", "!"); Console.WriteLine( "\t-KEY-\t-VALUE-" ); for ( int i = 0; i < myList.Count; i++ ) { Console.WriteLine( "\t{0}:\t{1}", myList.GetKey(i),&myList.GetByIndex(i) );
} Console.WriteLine();
6/5/2009
21
Translating C# Code Snippet to PowerScript
// PowerScript codeSortedList companiescompanies = create SortedList companies.Add("First", “Sybase")companies.Add("Second", “IBM") companies.Add("Third", “Microsoft")
Long ifor i = 0 to companies.Countlb_1.addItem(companies.GetKey(i) + “: “ + companies.GetByIndex(i));
next
Limitations in PowerBuilder 11
• Can’t consume generic classes– http://www.15seconds.com/issue/031024.htm
• Can’t define a PowerBuilder class that inherits from a .NET class• Can’t define a PowerBuilder class that implements a .NET interface• .NET classes, interfaces and enums can’t be used as function
parameters or return types.– Can’t use delegates that have parameters
• http://www.sellsbrothers.com/writing/default.aspx?content=delegates.htm
6/5/2009
22
Consuming Web ServicesIn .NET way
Consuming Web Services
Generating PB proxy for Web services• Use wsdl.exe to generate .NET proxy class• Use csc.exe (C# compiler) to compile the .NET proxy class• Write PB proxy for .NET proxy class
Wsdl.exe csc.exe Writing PB proxy
.wsdl .cs .dll PB NVO
Steps for generating PowerBuilder proxies for Web services
6/5/2009
23
Advantages of Using .NET interop
• No data marshalling between managed and unmanaged worlds• Able to deal with array of arrays or multidimensional arrays
Using GoogleSearchService
• Download wsdl file from http://api.google.com/GoogleSearch.wsdl. • Generate C# code
– Wsdl /namespace:GoogleSearchService GoogleSearch.wsdl
• Generate DLL– Csc /target:library /out:GoogleSearchServer.dll GoogleSearchService.cs
• Use .NET Reflector to examine the classes• Look for samples to see how to use the classes• Write PowerBuilder proxies
6/5/2009
24
Demo - GoogleSearch
.NET Reflector
Download from http://www.aisto.com/roeder/dotnet/
6/5/2009
25
Creating PowerBuilder Proxies
• Create an NVO for each .NET class– E.g. n_googleSearchService– Declare an instance variable of the .NET type to be wrapped.
• Write a function for each .NET function you want to call– doGoogleSearch– Map parameter types and return type– Call the .NET function in .NET code block
• Write a getter and/or setter for the .NET property or field you want to access
• If the return type is a jagged array, create a PowerBuilder proxy for the array.
Creating PowerBuilder Proxies
//function n_GoogleSearchResult doGoogleSearch(…)n_GoogleSearchResult result
#if defined pbdotnet then
result = create n_GoogleSearchResultresult._instance = _instance.doGoogleSearch(a_key, a_q, a_start, &a_maxResults, a_filter, a_restrict, a_safeSearch, a_lr, a_ie, a_oe)
#end if
return result
6/5/2009
26
Using .NET Classes in PowerBuilder
Q & A