Professional Documents
Culture Documents
Chris Sells
http://staff.develop.com/csells
1
Motivation
2
Recall: The Component Object Model
3
The .NET Common Language Runtime
• The .NET CLR is an OS add-on provided to support:
– Finding and loading classes
– Negotiating types exposing by COM classes
– Marshaling types between contexts
– Sandbox security
– Multi-language support, i.e. MC++, C#, VB, JS, Eiffel, Camel, et al
– Intermediate language representation (IL)
– JIT compilers
– Common type system
– Metadata and reflection
– Versioning
– Garbage collection
– XCOPY deployment
– Win32/COM/COM+ interop
4
Recall: The Active Template Library
5
Exposing a COM Class
6
Exposing a COM Class
// (1) Define the class’s default interface
[…] interface IBeachBall : IUnknown {
HRESULT Bounce();
}
7
Exposing a COM Class
class ATL_NO_VTABLE CBeachBall :
public CComObjectRootEx<…>,
// (3) Implement a class object
public CComCoClass<…>,
public IBeachBall {
public:
…
// (4) Expose the interface
BEGIN_COM_MAP(CBeachBall)
COM_INTERFACE_ENTRY(IBeachBall)
END_COM_MAP()
// (8) Register
STDAPI DllRegisterServer() {
return _Module.RegisterServer(TRUE);
}
9
ATL Simplifies
10
.NET Simplifies
11
The Mechanics of Managed C++
12
Managed Code
13
Managed Code
#using <mscorlib.dll>
using namespace System;
void main() {
Console::WriteLine(S"Hello, MC++");
}
C:\> cl /CLR hello.cpp
C:\> hello.exe
C:\> ildasm hello.exe
14
Managed Types
15
Example: MC++ Component
#using <mscorlib.dll>
using namespace System;
namespace DevelopMentorSample {
public __gc class HelloHolder {
public:
String* Hello;
String* GetHello() {
return Hello;
}
}; C:\> cl /LD /CLR hh.cpp /o hh.dll
} C:\> ildasm hh.dll
16
Example: MC++ Client
#using <mscorlib.dll>
using namespace System;
#using "hh.dll"
using namespace DevelopMentorSample;
void main() {
HelloHolder* hh = new HelloHolder;
hh->Hello = "hi";
Console::WriteLine(hh->GetHello());
}
C:\> cl /CLR hellocli.cpp
C:\> hellocli.exe
17
What Happened?
• We simplified
– No DllXxx entry points
– No extra mapping from COM to/from C++ types
– No “strange” types, e.g. BSTR, VARIANT, SAFEARRAY
– No HRESULTs (and therefore no retval)
– No get_/put_ property simulations
– No need for a formal interface
– No separate header files
• Conceptually, we didn’t do anything different…
18
From ATL/COM to .NET
19
Component Packaging
20
“Server Type”
21
.NET Assemblies
22
Assemblies Manifest Assembly 0
Assembly Declaration
…
Module Declaration
External Assembly
References (1..N)
Assembly M
23
Example .assembly paul
Manifest
<empty>
.assembly band
.module paul.dll
<empty>
Manifest
Manifest
<empty>
.class public Manager { .module john.dll
}
.assembly extern mscorlib
.class public JP {
.field [john]Singer m
}
24
Private vs. Global Assemblies
25
COM and DLL Hell
26
.NET and DLL Hell
27
Example: Different Versions
Monday’s
Child.exe Tuesday’s
Child.exe
Wednesday’s
Character.dll:1.0 Child.exe
(implemented with
“fairness of face”) Character.dll:1.1
(implemented with
“grace”) Character.dll:1.2
(implemented with
“woe”)
28
“Allow merging of proxy/stub code”
29
.NET Marshalling
30
.NET Marshalling
[Serializable]
public __gc class B {}; A B C
Clone Proxy
of B to C
AppDomain Y
Process M
31
COM Remoting
32
.NET Remoting
33
Example: .NET Remoting Server
void main() {
// Create object and bind to "myuri"
HelloHolder* hh = new HelloHolder;
ObjRef* or = RemotingServices::Marshal(hh,
S"myuri");
34
Example: .NET Remoting Client
void main() {
// Register HTTP channel
IChannel* ch = new Http::HttpChannel;
ChannelServices::RegisterChannel(ch);
// Build a proxy
System::Type* type = (new HelloHolder)->GetType();
HelloHolder* hh =
(HelloHolder*)RemotingServices::Connect(
type, "http://localhost:3456/myuri");
// Do something
hh->Hello = S"hi";
Console::WriteLine(hh->GetHello());
}
35
“Support MFC”
36
.NET Type System
Delegate MultiCastDelegate
37
.NET Framework
System Core type system types
System::Windows::Forms Desktop UI 38
“Support MTS”
39
.NET Enterprise Services
40
Example: .NET Transaction Services
using namespace System::EnterpriseServices;
[assembly: ApplicationName("MyApp")];
[assembly: AssemblyKeyFileAttribute("MyApp.key")];
[Transaction(TransactionOption::Required)]
public __gc class MyTx : public ServicedComponent {
public: void PerformService() {
if( !DoSomethingCritical() ) {
ContextUtil::MyTransactionVote =
TransactionVote::Abort;
}
}
}; C:\> cl /CLR /LD mytx.cpp /o mytx.dll
C:\> regsvcs mytx.dll
41
Components
42
“Names”
43
.NET Names
namespace Sample {
public __gc class MyClass {…};
}
#using <sample.dll>
MyClass* obj = new Sample::MyClass;
44
“CoClass”
IUnknown* punk = 0;
CoCreateInstance(CLSID_Foo, …, &punk);
45
“Interface”
IFoo* pfoo = 0;
punk->QueryInterface(IID_IFoo, &pfoo);
46
Resolving .NET Names
47
.NET Classes and Interfaces
namespace Pets {
public __gc __interface IDog {
public: void Bark();
};
public __gc class SmartDog : public IDog {
public: void Bark() {…}
void RollOver() {…}
};
} Object* obj = new Pets::Dog;
IDog* dog = __try_cast<IDog*>(obj);
dog->Bark();
SmartDog* fido = __try_cast<SmartDog*>(obj);
fido->RollOver();
48
COM Binding to Member Names
49
COM Binding to Member Names
m_cRef Foo::Release
Foo::DoFoo
Additional
Data Foo::QueryInterface
Members
Foo::AddRef
Foo::Release
Foo::DoBar
50
.NET Binding to Member Names
51
“Threading Model” and “FTM”
MTA no no
desired
TNA no no
FTM no no
N/A no yes
52
.NET Threading and Synchronization
[Synchronization(Synchronization::Required)]
public __gc class Rental :
public ContextBoundObject {};
53
.NET Synchronization
54
Example: .NET Synchronization
Monitor::Exit(this);
}
};
55
“Dual” vs. “Custom”
56
Example: COM Dynamic Binding
long RandomNext(IDispatch *pObj, long min, long max) {
// build vector of arguments
VARIANTARGS args[2] = { 0 };
args[1].vt = VT_I4; args[1].lVal = min;
args[0].vt = VT_I4; args[0].lVal = max;
DISPPARAMS params = { args, 0, 2, 0 };
// invoke method
VARIANT result = { 0 };
HRESULT hr = pObj->Invoke(DISPID_NEXT, IID_NULL, 0,
DISPATCH_METHOD, ¶ms, &result, 0, 0);
// coerce result to a long and clean up VARIANTs
if (SUCCEEDED(hr)) {
hr = VariantChangeType(&result, &result, 0, VT_I4);
}
VariantClear(&args[0]); VariantClear(&args[1]);
if (FAILED(hr)) throw hr;
return result.lVal;
} 57
.NET Dynamic Binding
58
.NET Reflection
using namespace System::Reflection;
void main() {
Type* t = Type::GetType(S"System.Random");
Object* obj = Activator::CreateInstance(t);
60
“Aggregation”
61
.NET Inheritance
63
.NET Exceptions
void BadDog() {
try { Bad(); }
catch( MyException* e ) { throw; }
catch(...) {}
__finally {}
}
64
“Support Connection Points”
65
.NET Events
66
What Do We Give Up?
67
COM Resource Management
68
Example: COM Resource Management
void UseFoo() {
CComPtr<IFoo> spfoo;
spfoo.CoCreateInstance(CLSID_Foo);
CComBSTR bstr;
spfoo->get_Name(&bstr);
70
Example: .NET Resource Management
void UseFoo() {
Foo* pfoo = new Foo();
String* str = pfoo->Name;
71
.NET Finalization
72
The Disposer Pattern
void f() {
MyClass* p;
try { p = new MyClass;… }
__finally { if( p ) p->Dispose(); }
}
73
The Rest
74
Mixing Managed and Unmanaged Code
// mixed.cpp
…managed code by default…
#pragma unmanaged
…unmanaged code…
#pragma managed
…managed code…
75
Calling Unmanaged Code
76
Example: Pinning Managed Data
HRESULT __stdcall VarI4FromI2(short sIn, long* plOut);
void main() {
ShortLong* sl = new ShortLong;
sl->n = 10;
VarI4FromI2(sl->n, &sl->l); // Compile-time error
77
C# is Cool
78
Hello, C#
using System;
class HelloCSharp {
public static void Main(string[] args) {
Console.WriteLine("Hello, C#");
}
}
79
C# Component
namespace com.develop.sample {
public class HelloHolder {
public string Hello = "Hello, C#";
public string GetHello() {
return Hello;
}
}
}
C:\> csc /t:library hh.cs
C:\> ildasm hh.dll
80
Component Client
using System;
using com.develop.sample;
class HelloHolderClient {
public static void Main() {
HelloHolder hh = new HelloHolder();
Console.WriteLine("From HH: " +
hh.GetHello());
Console.WriteLine("From HH: {0}",
hh.GetHello());
}
} C:\> csc /r:hh.dll hc.cs
C:\> hc.exe
81
The C# type system
object ValueType bool
long
byte
sbyte
enum char
•All types float
map to CLR Currency
string decimal
types in DateTime
“System” int
Array TimeSpan
namespace ushort
double
Exception uint
•Integral types Guid
fixed-width ulong
short
delegate void
82
Type Safety
struct Number {
public Number(long _n) { n = _n; }
public long n;
}
…
Number n1; n1.n = 4; // No ctor
Number n2 = new Number(4); // Ctor
84
Struct Are Not Classes
85
Interfaces
86
Class
class Number {
public Number(long _n) { n = _n; }
public long n = 0;
}
…
Number n1; // Just a reference
n1.n = 4; // ERR
87
Class Members
88
Access Modifiers
89
Fields and Properties
class Point {
public long x;
public long y {
get { return _y; }
set { _y = value; }
}
private long _y; Point pt = new Point();
} pt.x = 1;
pt.y = 2;
90
Method Arguments
92
Indexers
class Numbers {
public Numbers(int n)
{ _rg = new long[n]; }
public long this[int n] {
get { return _rg[n]; }
set { _rg[n] = value; }
}
private long[] _rg;
}
Numbers rg = new Numbers(10);
rg[0] = 1; Console.WriteLine(rg[0]);
93
Operator overloading
class Number {
public Number(long n) { _n = n; }
public static Number
operator+(Number n1, Number n2)
{ return new Number(n1._n + n2._n); }
public static implicit
operator long(Number n) { return n._n; }
private long _n;
};
94
Delegates
class Button {
public void Click() {
if( OnClick != null ) OnClick();
}
public event ClickHandler OnClick;
};
97
Inheritance
98
Function Overriding
class Base {
public virtual void foo() {…}
public void bar() {…}
}
class Derived {
public override void foo() {…}
public new void bar() {…}
}
99
System.Object
namespace System {
public class Object {
public Object();
public virtual Boolean Equals(Object rhs);
public virtual Int32 GetHashCode();
public Type GetType();
public virtual String ToString();
100
Example: Overriding ToString
class Number {
public Number(int n) { _n = n; }
private int _n;
public override string ToString()
{ return _n.ToString(); }
}
101
Overriding Finalize
class MyClass {
// Overrides Finalize()
~MyClass() {…}
}
102
C# Destructors Aren’t
103
The Disposer Pattern
void f() {
MyClass p;
try { p = new MyClass(); … }
finally { if( p ) p.Dispose(); }
}
104
C# Supports IDisposable Directly
void f() {
using( MyClass obj = new MyClass() ) {
// Use obj
} // (IDisposable)obj.Dispose() called
}
105
Sealed and Abstract Types
struct V {…}
class R {…}
V vt = new V; // stack
R rt = new R; // heap
107
Boxing and Unboxing
108
Example: Boxing and Unboxing
a 0
2 0
3
obj vptr 2
5 3
7
foo1
foo2 vptr 2
6 3
8
b 6 8 V a = new V();
a.g(2);
object obj = a; // box
IFoo foo1 = (IFoo)obj;
foo1.g(3);
IFoo foo2 = (IFoo)a; // box
foo2.g(4);
V b = (V)foo1; // unbox
109
Compilation Symbols
110
Conditional Compilation
111
Control Flow
switch( s ) {
case "one": …; break;
case "two": case "three": …; break;
default: …; goto case "one"; break;
}
112
The foreach statement
113
Exceptions
114
Example: Exceptions
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern int
MessageBox(int p, string t, string c, ulong f);
116
COM/.NET Interop
using Scripting;
• Templates
• Global functions
• Pointer arithmetic (except in unsafe sections)
• Scope resolution and arrow operators
• Deterministic finalization
• Local static variables
• Macros
119
Summary
120
References
121
Questions?
122