Eseményrendszer, delegátumok C#-ban

Download Report

Transcript Eseményrendszer, delegátumok C#-ban

Delegátumok C#-ban
Krizsán Zoltán
iit
1.0
Események kezelése
Nem kell vizuális felületnek lennie.
 Delegátumok segítségével
valósíthatja meg a .NET.

Krizsán Zoltán
iit
Delegátumok C#-ban
2
Delegátumok
Típusos fv. pointer
Biztonságos kódkészítés miatt tiltott
a pointer aritmetika a C#-ban.
 Fv. Pointer helyett delegátum
 Alakja:
delegate típus nev(tipus
param_nev,..)
 Ha megadjuk a paraméter típusát,
akkor a paraméter nevét is meg kell
adni!

Krizsán Zoltán
iit
Delegátumok C#-ban
3
Delegátum II.
Nem csak a fv. címe, de visszatérési
érték + paraméterek
 Amire hivatkozik, lehet:

• Statikus fv.
• Példány fv.
Krizsán Zoltán
iit
Delegátumok C#-ban
4
Példa
delegate void MyDelegate();
public class MyClass{
public void InstanceMethod(){Console.WriteLine("A message from
the instance method.");}
}
static public void StaticMethod(){Console.WriteLine("A message
from the static method.");}
public class MainClass{
static public void Main(){
MyClass p = new MyClass();
MyDelegate d = new MyDelegate( p.InstanceMethod ); d();
d = new MyDelegate( MyClass.StaticMethod ); d();
}
}
Krizsán Zoltán
iit
Delegátumok C#-ban
5
Részlet a Példa il kódjából
.class private auto ansi sealed MyDelegate extends
[mscorlib]System.MulticastDelegate{
.method public hidebysig specialname rtspecialname
instance void .ctor( object 'object',
native int 'method‘ ) runtime managed
{ } // end of method MyDelegate::.ctor
.method public hidebysig virtual instance void
Invoke() runtime managed { } // end of method MyDelegate::Invoke
.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult
BeginInvoke(class [mscorlib]System.AsyncCallback callback,
object 'object') runtime managed
{ } // end of method MyDelegate::BeginInvoke
.method public hidebysig newslot virtual
instance void EndInvoke(class [mscorlib]System.IAsyncResult result)
runtime managed { } // end of method MyDelegate::EndInvoke
} // end of class MyDelegate
Krizsán Zoltán
iit
Delegátumok C#-ban
6
MulticastDelegate
minden delegátum őse
_target (System.Object):
az objektumra referál, amely a call
back fv.-hez kapcsolódik (csak
példány fv. esetén).
 _methodPtr (System.Int32):
egész szám, amellyel a CLR
azonosítja a fv.-t.
 _prev (System.MulticastDelegate):
a láncolt lista előző elemére mutat.

Krizsán Zoltán
iit
Delegátumok C#-ban
7
MulticastDelegate II.

Két fontos tulajdonság:
• Target->_target
• Method->_methodPtr
Az Invoke fv. nem hívható meg
közvetlenül (VB-ben viszont
kötelező).
 Equals újradefiniált, igaz, ha _target
és _methodPtr azonosakra referál.

Krizsán Zoltán
iit
Delegátumok C#-ban
8
Delegátum lánc
A delegátum önmagában is hasznos,
de láncolt listára fűzve hatékonyabb
 _prev az előző elemre. Kezdetben
null, később áll be egy érvényes
objektumra.

Krizsán Zoltán
iit
Delegátumok C#-ban
9
System.Delegate
public static Delegate
Combine(Delegate tail, Delegate
head) : hozzáfűz a listához
 public static Delegate
Combine(Delegate[] delegateArray) :
hozzáfűz a listához
 public static Delegate
Remove(Delegate source, Delegate
value) : töröl a listából

Krizsán Zoltán
iit
Delegátumok C#-ban
10
System.Delegate C#-ban
public static Delegate Combine
helyett
operator+=
 public static Delegate Remove
helyett
operator-=

Krizsán Zoltán
iit
Delegátumok C#-ban
11
Példa II.-set osztály
class Set {
private Object[] items;
public Set(Int32 numItems){
items = new Object[numItems];
for (Int32 i =0; i < numItems; i++)
items[i] = i;
}
public delegate void Feedback(Object value, Int32 item, Int32 numItem);
}
public void ProcessItems( Feedback feedback ){
for(Int32 item = 0; item< items.Length(); item++){
if ( feedback != null ){ feedback(items[item], item+1,
items.Length); }
}
}
Krizsán Zoltán
iit
Delegátumok C#-ban
12
Példa II.-App
static void Main(){ StaticCallbacks(); InstanceCallbacks(); }
static void StaticCallbacks() {
Set setOfItems = new Set(5);
setOfItems.ProcessItems (null);Console.WriteLine();
setOfItems.ProcessItems ( new
Set.Feedback(App.FeedbackToConsole) );
Console.WriteLine();
setOfItems.ProcessItems ( new
Set.Feedback(App.FeedbackToMsgBox) );
Console.WriteLine();
Set.Feedback fb = null;
fb += new Set.Feedback(App.FeedbackToConsole);
fb += new Set.Feedback(App.FeedbackToMsgBox);
setOfItems.ProcessItems(fb);Console.WriteLine();
}
static void InstanceCallbacks() {
Set setOItems = new Set(5); App appobj = new App();
setOItems.ProcessItems( new
Set.Feedback(appobj.FeedbackToFile) );
Console.WriteLine();
}
Krizsán Zoltán
iit
Delegátumok C#-ban
13
Példa II.-App
static void FeedbackToConsole(Object value, Int32 item, Int32
numItems){
Console.WriteLine("Processing item {0} of {1}: {2}.",
item, numItems, value);
}
static void FeedbackToMsgBox(Object value, Int32 item, Int32
numItems){
MessageBox.Show(String.Format("Processing item {0} of {1}:
{2}.", item, numItems, value));
}
void FeedbackToFile(Object value, Int32 item, Int32 numItems){
StreamWriter sw = new StreamWriter("Status", true);
sw.WriteLine("Processing item {0} of {1}: {2}.",item,numItems,
value);
sw.Close();
}
Krizsán Zoltán
iit
Delegátumok C#-ban
14
IL kód


Nézzük meg az IL kódot!
feedback( items[item], item+1,
items.Length );
helyett:
IL_001b: callvirt instance void
Set/Feedback::Invoke(object, int32,
int32)
Krizsán Zoltán
iit
Delegátumok C#-ban
15
MulticastDelegate.Invoke
Public Int32 virtual Invoke(Object value,
Int32 item, Int32 numItem )
{
if (_prev != null)
_prev.Invoke( value, item,
numItems );
return _target.methodPtr(value,
item, numItems
}
Krizsán Zoltán
iit
Delegátumok C#-ban
16
Teljes kontroll a delegátum lánc
felett
public virtual Delegate[]
GetInvocationList()
 Klónozza a lista elemeit egy tömbbe,
de minden elem _prev-je null.
 A visszaadott tömbön
végigjárhatunk!

Krizsán Zoltán
iit
Delegátumok C#-ban
17
Példa III
class Light{
public String GetPosition() {
return "Villany felkapcsolva!";
}
}
class Fan{
public String Speed() {
throw new Exception("Nagyon gyors!");
}
}
class Speaker{
public String Volume() {
return "Nagyon hangos!";
}
}
Krizsán Zoltán
iit
Delegátumok C#-ban
18
Példa III-AppI
delegate string GetStatus();
static public void Main()
{
GetStatus getstatus = null;
getstatus += new GetStatus( new Light().GetPosition );
getstatus += new GetStatus( new Fan().Speed );
getstatus += new GetStatus( new Speaker().Volume );
}
Console.WriteLine(
GetComponentStatusReport(getstatus) );
Krizsán Zoltán
iit
Delegátumok C#-ban
19
Példa III-AppII
static String GetComponentStatusReport(GetStatus status){
if ( status == null) return null;
StringBuilder sb = new StringBuilder();
Delegate[] arrayOfDelegates = status.GetInvocationList();
foreach( GetStatus getstatus in arrayOfDelegates ){
try{
sb.AppendFormat("{0}{1}{1}", getstatus() ,
Environment.NewLine);
}
catch(Exception e){
Object o = getstatus.Target;
sb.AppendFormat("Hiba keletkezett: {1}{2}{0}
Hiba: {3}{0}{0}", Environment.NewLine,
((o == null) ? "" : o.GetType() + "."),
getstatus.Method.Name, e.Message);
}
}
return sb.ToString();
}
Krizsán Zoltán
iit
Delegátumok C#-ban
20