Nasıl yapılır: Temsilcileri Tanımlama ve Kullanma (C++/CLI)
Bu makalede C++/CLI'da temsilcileri tanımlama ve kullanma işlemleri gösterilmektedir.
.NET Framework bir dizi temsilci sağlasa da, bazen yeni temsilciler tanımlamanız gerekebilir.
Aşağıdaki kod örneği adlı MyCallback
bir temsilciyi tanımlar. Bu yeni temsilci tetiklendiğinde çağrılan işlev olan olay işleme kodunun dönüş türüne void
sahip olması ve başvuru String alması gerekir.
Ana işlev, temsilcinin örneğini MyCallback
oluşturmak için tarafından SomeClass
tanımlanan statik bir yöntem kullanır. Ardından temsilci, temsilci nesnesine "single" dizesini göndererek gösterildiği gibi bu işlevi çağırmak için alternatif bir yöntem haline gelir. Ardından, ek örnekleri MyCallback
birbirine bağlanır ve ardından temsilci nesnesine bir çağrı ile yürütülür.
// use_delegate.cpp
// compile with: /clr
using namespace System;
ref class SomeClass
{
public:
static void Func(String^ str)
{
Console::WriteLine("static SomeClass::Func - {0}", str);
}
};
ref class OtherClass
{
public:
OtherClass( Int32 n )
{
num = n;
}
void Method(String^ str)
{
Console::WriteLine("OtherClass::Method - {0}, num = {1}",
str, num);
}
Int32 num;
};
delegate void MyCallback(String^ str);
int main( )
{
MyCallback^ callback = gcnew MyCallback(SomeClass::Func);
callback("single");
callback += gcnew MyCallback(SomeClass::Func);
OtherClass^ f = gcnew OtherClass(99);
callback += gcnew MyCallback(f, &OtherClass::Method);
f = gcnew OtherClass(100);
callback += gcnew MyCallback(f, &OtherClass::Method);
callback("chained");
return 0;
}
static SomeClass::Func - single
static SomeClass::Func - chained
static SomeClass::Func - chained
OtherClass::Method - chained, num = 99
OtherClass::Method - chained, num = 100
Sonraki kod örneği, bir temsilcinin bir değer sınıfının üyesiyle nasıl ilişkilendirileceklerini gösterir.
// mcppv2_del_mem_value_class.cpp
// compile with: /clr
using namespace System;
public delegate void MyDel();
value class A {
public:
void func1() {
Console::WriteLine("test");
}
};
int main() {
A a;
A^ ah = a;
MyDel^ f = gcnew MyDel(a, &A::func1); // implicit box of a
f();
MyDel^ f2 = gcnew MyDel(ah, &A::func1);
f2();
}
test
test
Temsilci oluşturma
Bir bileşen temsilcisini oluşturulan temsilciden kaldırmak için "-
" işlecini kullanabilirsiniz.
// mcppv2_compose_delegates.cpp
// compile with: /clr
using namespace System;
delegate void MyDelegate(String ^ s);
ref class MyClass {
public:
static void Hello(String ^ s) {
Console::WriteLine("Hello, {0}!", s);
}
static void Goodbye(String ^ s) {
Console::WriteLine(" Goodbye, {0}!", s);
}
};
int main() {
MyDelegate ^ a = gcnew MyDelegate(MyClass::Hello);
MyDelegate ^ b = gcnew MyDelegate(MyClass::Goodbye);
MyDelegate ^ c = a + b;
MyDelegate ^ d = c - a;
Console::WriteLine("Invoking delegate a:");
a("A");
Console::WriteLine("Invoking delegate b:");
b("B");
Console::WriteLine("Invoking delegate c:");
c("C");
Console::WriteLine("Invoking delegate d:");
d("D");
}
Çıktı
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
Bir temsilciyi^ işlev işaretçisi bekleyen yerel bir işleve geçirme
Yönetilen bir bileşenden, yerel işlevin yönetilen bileşenin temsilcisinin üye işlevini çağırabildiği işlev işaretçisi parametreleriyle yerel bir işlevi çağırabilirsiniz.
Bu örnek, yerel işlevi dışarı aktaran .dll oluşturur:
// delegate_to_native_function.cpp
// compile with: /LD
#include < windows.h >
extern "C" {
__declspec(dllexport)
void nativeFunction(void (CALLBACK *mgdFunc)(const char* str)) {
mgdFunc("Call to Managed Function");
}
}
Sonraki örnek, .dll kullanır ve işlev işaretçisi bekleyen yerel işleve bir temsilci tanıtıcısı geçirir.
// delegate_to_native_function_2.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;
delegate void Del(String ^s);
public ref class A {
public:
void delMember(String ^s) {
Console::WriteLine(s);
}
};
[DllImportAttribute("delegate_to_native_function", CharSet=CharSet::Ansi)]
extern "C" void nativeFunction(Del ^d);
int main() {
A ^a = gcnew A;
Del ^d = gcnew Del(a, &A::delMember);
nativeFunction(d); // Call to native function
}
Çıktı
Call to Managed Function
Temsilcileri yönetilmeyen işlevlerle ilişkilendirmek için
Bir temsilciyi yerel bir işlevle ilişkilendirmek için, yerel işlevi yönetilen bir türe sarmalamanız ve aracılığıyla PInvoke
çağrılacak işlevi bildirmeniz gerekir.
// mcppv2_del_to_umnangd_func.cpp
// compile with: /clr
#pragma unmanaged
extern "C" void printf(const char*, ...);
class A {
public:
static void func(char* s) {
printf(s);
}
};
#pragma managed
public delegate void func(char*);
ref class B {
A* ap;
public:
B(A* ap):ap(ap) {}
void func(char* s) {
ap->func(s);
}
};
int main() {
A* a = new A;
B^ b = gcnew B(a);
func^ f = gcnew func(b, &B::func);
f("hello");
delete a;
}
Çıktı
hello
İlişkisiz temsilcileri kullanmak için
temsilci çağrıldığında işlevini çağırmak istediğiniz türün bir örneğini geçirmek için ilişkisiz bir temsilci kullanabilirsiniz.
İlişkisiz temsilciler, özellikle bir koleksiyondaki nesneleri yinelemek (her biri için anahtar sözcüklerde) kullanmak ve her örnekte bir üye işlevi çağırmak istiyorsanız kullanışlıdır.
İlişkili ve ilişkisiz temsilcileri bildirme, örnekleme ve çağırma işlemleri şöyle yapılır:
Eylem | Bağlı Temsilciler | İlişkisiz Temsilciler |
---|---|---|
Bildirmek | Temsilci imzası, temsilci aracılığıyla çağırmak istediğiniz işlevin imzası ile eşleşmelidir. | Temsilci imzasının ilk parametresi, çağırmak istediğiniz nesnenin türüdür this .İlk parametreden sonra, temsilci imzası temsilci aracılığıyla çağırmak istediğiniz işlevin imzası ile eşleşmelidir. |
Örneğini | Bağlı bir temsilci örneği oluştururken, bir örnek işlevi veya genel veya statik üye işlevi belirtebilirsiniz. Bir örnek işlevi belirtmek için, ilk parametre üye işlevini çağırmak istediğiniz türün bir örneği, ikinci parametre ise çağırmak istediğiniz işlevin adresidir. Genel veya statik üye işlevini çağırmak istiyorsanız, genel bir işlevin adını veya statik üye işlevinin adını geçirmeniz gerekir. |
İlişkisiz bir temsilci örneği oluştururken, çağırmak istediğiniz işlevin adresini geçirmeniz yeter. |
Call | Bağlı bir temsilciyi çağırdığınızda, temsilci imzası için gereken parametreleri geçirmeniz yeter. | Bağlı temsilciyle aynı, ancak ilk parametrenin çağırmak istediğiniz işlevi içeren nesnenin bir örneği olması gerektiğini unutmayın. |
Bu örnek, ilişkisiz temsilcileri bildirmeyi, örneği oluşturmayı ve çağırmayı gösterir:
// unbound_delegates.cpp
// compile with: /clr
ref struct A {
A(){}
A(int i) : m_i(i) {}
void Print(int i) { System::Console::WriteLine(m_i + i);}
private:
int m_i;
};
value struct V {
void Print() { System::Console::WriteLine(m_i);}
int m_i;
};
delegate void Delegate1(A^, int i);
delegate void Delegate2(A%, int i);
delegate void Delegate3(interior_ptr<V>);
delegate void Delegate4(V%);
delegate void Delegate5(int i);
delegate void Delegate6();
int main() {
A^ a1 = gcnew A(1);
A% a2 = *gcnew A(2);
Delegate1 ^ Unbound_Delegate1 = gcnew Delegate1(&A::Print);
// delegate takes a handle
Unbound_Delegate1(a1, 1);
Unbound_Delegate1(%a2, 1);
Delegate2 ^ Unbound_Delegate2 = gcnew Delegate2(&A::Print);
// delegate takes a tracking reference (must deference the handle)
Unbound_Delegate2(*a1, 1);
Unbound_Delegate2(a2, 1);
// instantiate a bound delegate to an instance member function
Delegate5 ^ Bound_Del = gcnew Delegate5(a1, &A::Print);
Bound_Del(1);
// instantiate value types
V v1 = {7};
V v2 = {8};
Delegate3 ^ Unbound_Delegate3 = gcnew Delegate3(&V::Print);
Unbound_Delegate3(&v1);
Unbound_Delegate3(&v2);
Delegate4 ^ Unbound_Delegate4 = gcnew Delegate4(&V::Print);
Unbound_Delegate4(v1);
Unbound_Delegate4(v2);
Delegate6 ^ Bound_Delegate3 = gcnew Delegate6(v1, &V::Print);
Bound_Delegate3();
}
Çıktı
2
3
2
3
2
7
8
7
8
7
Sonraki örnekte, bir koleksiyondaki nesneler arasında yineleme yapmak ve her örnekte üye işlevi çağırmak için anahtar sözcüklerde ilişkisiz temsilcilerin ve her biri için öğesinin nasıl kullanılacağı gösterilmektedir.
// unbound_delegates_2.cpp
// compile with: /clr
using namespace System;
ref class RefClass {
String^ _Str;
public:
RefClass( String^ str ) : _Str( str ) {}
void Print() { Console::Write( _Str ); }
};
delegate void PrintDelegate( RefClass^ );
int main() {
PrintDelegate^ d = gcnew PrintDelegate( &RefClass::Print );
array< RefClass^ >^ a = gcnew array<RefClass^>( 10 );
for ( int i = 0; i < a->Length; ++i )
a[i] = gcnew RefClass( i.ToString() );
for each ( RefClass^ R in a )
d( R );
Console::WriteLine();
}
Bu örnek, bir özelliğin erişimci işlevleri için ilişkisiz bir temsilci oluşturur:
// unbound_delegates_3.cpp
// compile with: /clr
ref struct B {
property int P1 {
int get() { return m_i; }
void set(int i) { m_i = i; }
}
private:
int m_i;
};
delegate void DelBSet(B^, int);
delegate int DelBGet(B^);
int main() {
B^ b = gcnew B;
DelBSet^ delBSet = gcnew DelBSet(&B::P1::set);
delBSet(b, 11);
DelBGet^ delBGet = gcnew DelBGet(&B::P1::get);
System::Console::WriteLine(delBGet(b));
}
Çıktı
11
Aşağıdaki örnekte, bir örneğin bağlı ve bir örneğin ilişkisiz olduğu çok noktaya yayın temsilcisinin nasıl çağrılacağı gösterilmektedir.
// unbound_delegates_4.cpp
// compile with: /clr
ref class R {
public:
R(int i) : m_i(i) {}
void f(R ^ r) {
System::Console::WriteLine("in f(R ^ r)");
}
void f() {
System::Console::WriteLine("in f()");
}
private:
int m_i;
};
delegate void Del(R ^);
int main() {
R ^r1 = gcnew R(11);
R ^r2 = gcnew R(12);
Del^ d = gcnew Del(r1, &R::f);
d += gcnew Del(&R::f);
d(r2);
};
Çıktı
in f(R ^ r)
in f()
Sonraki örnekte, ilişkisiz genel temsilci oluşturma ve çağırma gösterilmektedir.
// unbound_delegates_5.cpp
// compile with: /clr
ref struct R {
R(int i) : m_i(i) {}
int f(R ^) { return 999; }
int f() { return m_i + 5; }
int m_i;
};
value struct V {
int f(V%) { return 999; }
int f() { return m_i + 5; }
int m_i;
};
generic <typename T>
delegate int Del(T t);
generic <typename T>
delegate int DelV(T% t);
int main() {
R^ hr = gcnew R(7);
System::Console::WriteLine((gcnew Del<R^>(&R::f))(hr));
V v;
v.m_i = 9;
System::Console::WriteLine((gcnew DelV<V >(&V::f))(v) );
}
Çıktı
12
14