Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Jótanács
Ha korábban már elolvasta ezt a témakört, és egy adott tevékenységgel tér vissza hozzá, akkor a témakör szakasza alapján ugorjon a
Ez a témakör átfogóan katalogizálja a forráskód
Az Univerzális Windows Platform (UWP) egyik alkalmazásminta portolásával kapcsolatos esettanulmányért tekintse meg a kapcsolódó témát: A Vágólap minta portolása C#-ról C++/WinRT-re. A portolási gyakorlatot és a tapasztalatot úgy szerezheti meg, ha végigköveti ezt az útmutatót, és menet közben magának is portolja a mintát.
A felkészülés és a várható teendők
Az esettanulmány A vágólap mintájának C++/WinRT-fájlba való portolása C#-ból példákat mutat be a projekt C+++/WinRT-be történő portolása során meghozott szoftvertervezési döntésekre. Ezért érdemes felkészülni a portolásra, ha alapos ismereteket szerez a meglévő kód működéséről. Így jó áttekintést kaphat az alkalmazás funkcióiról és a kód szerkezetéről, majd a meghozott döntések mindig a megfelelő irányba viszik előre.
A várható adathordozási változások tekintetében négy kategóriába csoportosíthatja őket.
-
A nyelvi kivetítésportja. A Windows Futtatókörnyezet (WinRT) különböző programozási nyelvekre kivetítve. Ezek a nyelvi vetületek úgy vannak kialakítva, hogy idiomatikusnak tűnjenek a szóban forgó programozási nyelvben. A C# esetében egyes Windows-futtatókörnyezet-típusok .NET-típusokként vannak kivetítve. Így például System.Collections.Generic.IReadOnlyList<T> -ot vissza Windows.Foundation.Collections.IVectorView<T>formátumra fordítja. A C#-ban is néhány Windows-futtatókörnyezeti művelet kényelmes C#-nyelvi funkciókként van előrevetítve. A C#-ban például az
+=operátor szintaxisával regisztrálhat egy eseménykezelő meghatalmazottat. Ezért az olyan nyelvi funkciókat fogja lefordítani, amelyek az éppen végrehajtás alatt álló alapvető művelethez kapcsolódnak (például eseményregisztráció ebben az esetben). -
portnyelv szintaxisa. Ezek közül sok egyszerű mechanikai átalakítás, amely egy szimbólumot cserél egy másikra. Például a pont (
.) kettőspontra (::) való módosítása. -
portnyelvi eljárás. Ezek némelyike lehet egyszerű, ismétlődő módosítás (például
myObject.MyPropertymyObject.MyProperty()). Másoknak mélyebb változásokra van szükségük (például egy olyan eljárás portolására, amely magában foglalja a System.Text.StringBuilder használatát egy olyanra, amely a std::wostringstreamhasználatát foglalja magában). -
C++/WinRTspecifikus portolással kapcsolatos feladatok. A Windows Futtatókörnyezet bizonyos részleteiről a C# implicit módon gondoskodik, a színfalak mögött. Ezek a részletek kifejezetten a C++/WinRT-ben érhetők el. Ilyen például, ha egy
.idlfájllal definiálja a futtatókörnyezeti osztályokat.
Az alábbi feladatalapú index után a témakör többi szakasza a fenti osztályozás szerint van strukturálva.
Tartalom keresése az éppen elvégzett feladat alapján
| Feladatok | Tartalom |
|---|---|
| Windows-futtatókörnyezeti összetevő (WRC) létrehozása | Bizonyos funkciók (vagy bizonyos API-k) csak C++-val érhetők el. Ezt a funkciót beleszámíthatja egy C++/WinRT WRC-be, majd felhasználhatja a WRC-t (például) egy C#-alkalmazásból. Lásd: Windows-futtatókörnyezeti összetevők C++/WinRT és Ha futtatókörnyezeti osztályt hoz létre windowsos futtatókörnyezeti összetevőben. |
| Egy aszinkron metódus portolása | Érdemes a C++/WinRT futtatókörnyezet osztályának aszinkron metódusát úgy kezdeni, hogy az első sor auto lifetime = get_strong(); legyen (lásd: Az osztálytag koroutinemutatójának biztonságos elérése).A Taskportolása: Aszinkron művelet.A Task<T>portolása, lásd aszinkron művelet.A portolás async void-tól, lásd a "tűz és felejtsd el" módszert. |
| Osztály átvitele | Először állapítsa meg, hogy az osztálynak futtatókörnyezeti osztálynak kell-e lennie, vagy lehet-e egy szokásos osztály. Az eldöntéshez tekintse meg a Szerzői API-k C++/WinRTlegelső részét. Ezután tekintse meg az alábbi három sort. |
| Egy futtatókörnyezeti osztály portja | Olyan osztály, amely a C++ alkalmazáson kívüli funkciókat osztja meg, vagy egy XAML-adatkötésben használt osztály. Lásd: Ha futtatókörnyezeti osztályt hoz létre windowsos futtatókörnyezeti összetevőben, vagy Ha az XAML felhasználói felületénhivatkozni szeretne egy futtatókörnyezeti osztályra. Ezek a hivatkozások részletesebben ismertetik ezt, de egy futtatókörnyezeti osztályt idL-ben kell deklarálni. Ha a projekt már tartalmaz egy IDL-fájlt (például Project.idl), akkor javasoljuk, hogy az új futási osztályt ebben a fájlban deklarálja. Az IDL-ben deklaráljon minden olyan metódust és adattagot, amelyet az alkalmazáson kívül fognak használni, vagy amelyeket az XAML-ben fognak használni. Az IDL-fájl frissítése után újraépítheti és megtekintheti a létrehozott csonkfájlokat (.h és .cpp) a projekt Generated Files mappájában (a Megoldáskezelőbena projektcsomópont ki van jelölve, és győződjön meg arról, hogy Az összes fájl megjelenítése be van kapcsolva). Hasonlítsa össze a csonkfájlokat a projektben már szereplő fájlokkal, adjon hozzá fájlokat, vagy szükség szerint adjon hozzá/frissítse a függvény-aláírásokat. A Stub-fájl szintaxisa mindig helyes, ezért azt javasoljuk, hogy a buildelési hibák minimalizálása érdekében használja. Ha a projektben lévő csonkok megegyeznek a csonkfájlokban találhatóakkal, a C#-kód áthordásával implementálhatja őket. |
| Szokásos osztály portja | Lásd: Ha nem futtatókörnyezeti osztályt létrehozni. |
| Szerző IDL |
Bevezetés a Microsoft Interface Definition Language 3.0 Ha olyan futtatókörnyezeti osztályt hoz létre, amelyet az XAML felhasználói felületén szeretne hivatkozni XAML-jelölő objektumainak felhasználása Futtatókörnyezeti osztályok definiálása IDL |
| Gyűjtemény átvitele |
Gyűjtemények a C++/WinRT-vel Adatforrás elérhetővé tétele az XAML-jelölő számára asszociatív tároló vektortagok hozzáférése |
| Esemény portolása |
Eseménykezelői delegált osztálytagként Eseménykezelő delegált visszavonása |
| Metódus portja | C#-ból: private async void SampleButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { ... }A C++/WinRT .h fájlhoz: fire_and_forget SampleButton_Tapped(IInspectable const&, RoutedEventArgs const&);A C++/WinRT .cpp fájlhoz: fire_and_forget OcrFileImage::SampleButton_Tapped(IInspectable const&, RoutedEventArgs const&) {...} |
| Port karakterláncok |
A karakterlánc-kezelés a C++/WinRT-ben ToString karakterlánc-építés Egy sztring dobozolása és kicsomagolása |
| Típuskonvertálás (típuskonverzió) | C#: o.ToString()C++/WinRT: to_hstring(static_cast<int>(o))Lásd még ToString. C#: (Value)oC++/WinRT: unbox_value<Value>(o)Dob, ha a kicsomagolás sikertelen. Lásd még: Boxing and unboxing. C#: o as Value? ?? fallbackC++/WinRT: unbox_value_or<Value>(o, fallback)Alapértelmezett értéket ad vissza, ha a kicsomagolás sikertelen. Lásd még: Boxing and unboxing. C#: (Class)oC++/WinRT: o.as<Class>()Dob, ha az átalakítás sikertelen. C#: o as ClassC++/WinRT: o.try_as<Class>()Null értéket ad vissza, ha az átalakítás sikertelen. |
A nyelvi kivetítés részét képező módosítások
| Kategória | C# | C++/WinRT | Lásd még |
|---|---|---|---|
| Nem beírt objektum |
objectvagy System.Object |
Windows::Foundation::IInspectable | Az EnableClipboardContentChangedNotifications metódus portolása |
| Vetületi névterek | using System; |
using namespace Windows::Foundation; |
|
using System.Collections.Generic; |
using namespace Windows::Foundation::Collections; |
||
| Gyűjtemény mérete | collection.Count |
collection.Size() |
A BuildClipboardFormatsOutputString metódus portolása |
| Tipikus gyűjteménytípus | IList<T>, és hozzáadása elem hozzáadásához. | IVector<T>, és Hozzáfűző elem hozzáadásához. Ha bárhol használ egy std::vector-t, akkor a push_back-t használja egy elem hozzáadásához. | |
| Írásvédett gyűjteménytípus | IReadOnlyList<T> | IVectorView<T> | A BuildClipboardFormatsOutputString metódus portolása |
| eseménykezelő delegált osztálytagként | myObject.EventName += Handler; |
token = myObject.EventName({ get_weak(), &Class::Handler }); |
Az EnableClipboardContentChangedNotifications metódus portolása |
| Eseménykezelő delegáltának visszavonása | myObject.EventName -= Handler; |
myObject.EventName(token); |
Az EnableClipboardContentChangedNotifications metódus portolása |
| asszociatív tároló | IDictionary<K, V> | IMap<K, V> | |
| vektortag hozzáférés | x = v[i];v[i] = x; |
x = v.GetAt(i);v.SetAt(i, x); |
Eseménykezelő regisztrálása/visszavonása
A C++/WinRT-ben számos szintaktikai lehetőség áll rendelkezésre, amelyekkel regisztrálhat vagy visszavonhat egy eseménykezelő delegáltat, amint azt az Események kezelése delegáltak használatával C++/WinRT-bencímű részben ismertetjük. Lásd még
Előfordulhat például, hogy amikor egy esemény címzettje (egy eseményt kezelő objektum) megsemmisül, vissza kell vonnia egy eseménykezelőt, hogy az eseményforrás (az eseményt növelő objektum) ne hívjon fel megsemmisült objektumot. Lásd : A regisztrált meghatalmazott visszavonása. Ilyen esetekben hozzon létre egy event_token tagváltozót az eseménykezelők számára. Például lásd: A EnableClipboardContentChangedNotifications metódus portolását.
Eseménykezelőt is regisztrálhat XAML jelölőnyelvben.
<Button x:Name="OpenButton" Click="OpenButton_Click" />
A C#-ban a OpenButton_Click metódus lehet privát, és az XAML továbbra is képes csatlakoztatni azt a ButtonBase.Click eseményhez, amelyet a OpenButtonvált ki.
C++/WinRT-ben a OpenButton_Click metódusnak nyilvánosnak kell lennie az implementálási típusban, ha regisztrálni szeretné a XAML-jelölőnyelvben. Ha csak imperatív kódban regisztrál egy eseménykezelőt, akkor az eseménykezelőnek nem kell nyilvánosnak lennie.
namespace winrt::MyProject::implementation
{
struct MyPage : MyPageT<MyPage>
{
void OpenButton_Click(
winrt::Windows:Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& args);
}
};
Alternatívaként a regisztrációs XAML-oldalt a megvalósítási típus "barátjaként" definiálhatja a programkódban, és a OpenButton_Click függvényt priváttá teheti.
namespace winrt::MyProject::implementation
{
struct MyPage : MyPageT<MyPage>
{
private:
friend MyPageT;
void OpenButton_Click(
winrt::Windows:Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& args);
}
};
Az egyik utolsó forgatókönyv az, amikor a
<Button x:Name="OpenButton" Click="{x:Bind OpenButton_Click}" />
Egyszerűen módosíthatja azt a jelölést az egyszerűbb Click="OpenButton_Click"formátumra. Vagy ha úgy tetszik, megtarthatja a jelöléseket úgy, ahogy vannak. Mindössze annyit kell tennie, hogy az eseménykezelőt az IDL-ben deklarálja.
void OpenButton_Click(Object sender, Windows.UI.Xaml.RoutedEventArgs e);
Megjegyzés:
Deklarálja a függvényt void akkor is, ha implementáljaTűzként, és felejtse el.
A nyelvi szintaxist érintő módosítások
| Kategória | C# | C++/WinRT | Lásd még |
|---|---|---|---|
| Hozzáférési módosítók | public \<member\> |
public:\<member\> |
A Button_Click metódus portolása |
| Hozzáférés egy adattaghoz | this.variable |
this->variable |
|
| Aszinkron művelet | async Task ... |
IAsyncAction ... |
IAsyncAction interfész, párhuzamossági és aszinkron műveletek C++/WinRT |
| Aszinkron művelet | async Task<T> ... |
IAsyncOperation<T> ... |
IAsyncOperation interfész, egyidejűség és aszinkron műveletek C++/WinRT |
| Fire-and-Forget metódus (aszinkront jelent) | async void ... |
winrt::fire_and_forget ... |
CopyButton_Click metódus portolása, Tüzelj és felejtsd el |
| Enumerált állandó elérése | E.Value |
E::Value |
DisplayChangedFormats metódus átültetése |
| Kooperatív várakozás | await ... |
co_await ... |
A CopyButton_Click metódus portolása |
| A tervezett típusok gyűjteménye privát mezőként | private List<MyRuntimeClass> myRuntimeClasses = new List<MyRuntimeClass>(); |
std::vector<MyNamespace::MyRuntimeClass>m_myRuntimeClasses; |
|
| GUID-konstrukció | private static readonly Guid myGuid = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1"); |
winrt::guid myGuid{ 0xC380465D, 0x2271, 0x428C, { 0x9B, 0x83, 0xEC, 0xEA, 0x3B, 0x4A, 0x85, 0xC1} }; |
|
| Névtérelválasztó | A.B.T |
A::B::T |
|
| Nulla | null |
nullptr |
Az UpdateStatus metódus átvitele |
| Típusobjektum beszerzése | typeof(MyType) |
winrt::xaml_typename<MyType>() |
Forgatókönyvek tulajdonság portolása |
| Metódus paraméterdeklarációja | MyType |
MyType const& |
Paraméterátadás |
| Paraméterdeklaráció aszinkron metódushoz | MyType |
MyType |
Paraméterátadás |
| Statikus metódus meghívása | T.Method() |
T::Method() |
|
| Húrok |
stringvagy System.String |
winrt::hstring | A karakterlánc-kezelés a C++/WinRT-ben |
| Sztring-konstans | "a string literal" |
L"a string literal" |
Konstruktor portolása, Jelenlegi, és FEATURE_NAME |
| Kikövetkeztetett (vagy dedukált) típus | var |
auto |
A BuildClipboardFormatsOutputString metódus portolása |
| Irányelv használata | using A.B.C; |
using namespace A::B::C; |
Konstruktor portolása, Jelenlegi, és FEATURE_NAME |
| Verbatim/nyers karakterlánc-literál | @"verbatim string literal" |
LR"(raw string literal)" |
DisplayToast metódus portolása |
Megjegyzés:
Ha egy fejlécfájl nem tartalmaz egy adott névtér using namespace irányelvét, akkor az adott névtér összes típusnevét teljes mértékben minősíteni kell; vagy legalább megfelelőnek kell minősítenie őket ahhoz, hogy a fordító megtalálja őket. Példaként lásd a DisplayToast metódusportolását.
Osztályok és tagok átvitele
Minden C#-típus esetében el kell döntenie, hogy windowsos futtatókörnyezeti típusba vagy normál C++ osztályba/struct/enumerálásba szeretné-e portolni. További információkért és részletes példákért, amelyek bemutatják, hogyan hozhatja meg ezeket a döntéseket, olvassa el a A vágólap mintájának portolása C++/WinRT-re C#-ből.
A C#-tulajdonság általában egy kiegészítő függvény, egy mutációs függvény és egy háttéradat-tag lesz. A további információért és példáért lásd a a IsClipboardContentChangedEnabled tulajdonságportolását.
A nem statikus mezőket tegye a implementációs típusadattagjaivá.
A C# statikus mező C++/WinRT statikus kiegészítő és/vagy mutációs függvény lesz. További információ és példa: Konstruktor portolása, Aktuálisés FEATURE_NAME.
A tagfüggvények esetében ismét el kell döntenie, hogy mindegyik az IDL-hez tartozik-e, vagy az ön implementációs típusának nyilvános vagy privát tagfüggvénye-e. További információkért és a döntési módra vonatkozó példákért tekintse meg a
XAML jelölés és erőforrásfájlok portolása
Abban az esetben, ha a vágólap példáját átültetjük C++/WinRT-re C#-ból, ugyanazt a XAML jelöléseket (beleértve az erőforrásokat) és eszközfájlokat használhattuk a C# és a C++/WinRT projektekben. Bizonyos esetekben a korrektúra szerkesztése szükséges lesz ennek eléréséhez. Lásd: Másolja az XAML kódot és a stílusokat, amelyek szükségesek a portolás befejezéséhez MainPage.
A nyelven belüli eljárásokat érintő változások
| Kategória | C# | C++/WinRT | Lásd még |
|---|---|---|---|
| Élettartam-kezelés aszinkron metódusban | Nincs adat. |
auto lifetime{ get_strong() }; vagyauto lifetime = get_strong(); |
A CopyButton_Click metódus portolása |
| Megszabadulás | using (var t = v) |
auto t{ v };t.Close(); // or let wrapper destructor do the work |
CopyImage függvény portolása |
| Objektum létrehozása | new MyType(args) |
MyType{ args } vagyMyType(args) |
Forgatókönyvek tulajdonság portolása |
| Nem inicializált referencia létrehozása | MyType myObject; |
MyType myObject{ nullptr }; vagyMyType myObject = nullptr; |
Konstruktor portolása, Jelenlegi, és FEATURE_NAME |
| Objektum hozzárendelése változóhoz argokkal | var myObject = new MyType(args); |
auto myObject{ MyType{ args } }; vagy auto myObject{ MyType(args) }; vagy auto myObject = MyType{ args }; vagy auto myObject = MyType(args); vagy MyType myObject{ args }; vagy MyType myObject(args); |
Footer_Click metódus portolása |
| Objektum létrehozása és hozzárendelése egy változóhoz argumentumok nélkül | var myObject = new T(); |
MyType myObject; |
A BuildClipboardFormatsOutputString metódus portolása |
| Objektum-inicializálási rövidítés | var p = new FileOpenPicker{ViewMode = PickerViewMode.List}; |
FileOpenPicker p;p.ViewMode(PickerViewMode::List); |
|
| Tömeges vektorművelet | var p = new FileOpenPicker{FileTypeFilter = { ".png", ".jpg", ".gif" }}; |
FileOpenPicker p;p.FileTypeFilter().ReplaceAll({ L".png", L".jpg", L".gif" }); |
A CopyButton_Click metódus portolása |
| Iterálás a gyűjteményen keresztül | foreach (var v in c) |
for (auto&& v : c) |
A BuildClipboardFormatsOutputString metódus portolása |
| Kivétel elfogása | catch (Exception ex) |
catch (winrt::hresult_error const& ex) |
PasteButton_Click függvény portolása |
| Kivétel részletei | ex.Message |
ex.message() |
PasteButton_Click függvény portolása |
| Tulajdonságérték lekérése | myObject.MyProperty |
myObject.MyProperty() |
NotifyUser metódus portolása |
| Tulajdonságérték beállítása | myObject.MyProperty = value; |
myObject.MyProperty(value); |
|
| Tulajdonságérték növelése | myObject.MyProperty += v; |
myObject.MyProperty(thing.Property() + v);Sztringek esetén váltson összeállítóra |
|
| ToString() | myObject.ToString() |
winrt::to_hstring(myObject) |
ToString() |
| Nyelvi sztring a Windows futtatókörnyezet sztringjéhez | Nincs adat. | winrt::hstring{ s } |
|
| Sztringépítés | StringBuilder builder;builder.Append(...); |
std::wostringstream builder;builder << ...; |
karakterlánc-építés |
| Sztring interpolációja | $"{i++}) {s.Title}" |
winrt::to_hstring, és/vagy winrt::hstring::operator+ | OnNavigatedTo függvény átvitele |
| Üres sztring összehasonlításhoz | System.String.Empty | winrt::hstring::empty | Az UpdateStatus metódus átvitele |
| Üres sztring létrehozása | var myEmptyString = String.Empty; |
winrt::hstring myEmptyString{ L"" }; |
|
| Szótárműveletek | map[k] = v; // replaces any existingv = map[k]; // throws if not presentmap.ContainsKey(k) |
map.Insert(k, v); // replaces any existingv = map.Lookup(k); // throws if not presentmap.HasKey(k) |
|
| Típuskonvertálás (hiba esetén) | (MyType)v |
v.as<MyType>() |
Footer_Click metódus portolása |
| Típuskonvertálás (hiba esetén null érték) | v as MyType |
v.try_as<MyType>() |
PasteButton_Click függvény portolása |
| A x:Name tulajdonságú XAML-elemek | MyNamedElement |
MyNamedElement() |
Konstruktor portolása, Jelenlegi, és FEATURE_NAME |
| Váltás a felhasználói felületi szálra | CoreDispatcher.RunAsync | CoreDispatcher.RunAsyncvagy winrt::resume_foreground | A NotifyUser metódus portolása,és a HistoryAndRoaming metódus portolása. |
| Felhasználói felületi elem felépítése imperatív kódban XAML-lapon | Lásd felhasználói felületi elem építése | Lásd felhasználói felületi elem építése |
Az alábbi szakaszok részletesebben ismertetik a táblázat egyes elemeit.
Felhasználói felületi elem felépítése
Ezek a példakódok egy felhasználói felületi elem felépítését mutatják be egy XAML-oldal imperatív kódjában.
var myTextBlock = new TextBlock()
{
Text = "Text",
Style = (Windows.UI.Xaml.Style)this.Resources["MyTextBlockStyle"]
};
TextBlock myTextBlock;
myTextBlock.Text(L"Text");
myTextBlock.Style(
winrt::unbox_value<Windows::UI::Xaml::Style>(
Resources().Lookup(
winrt::box_value(L"MyTextBlockStyle")
)
)
);
ToString()
A C#-típusok biztosítják a Object.ToString metódust.
int i = 2;
var s = i.ToString(); // s is a System.String with value "2".
A C++/WinRT közvetlenül nem biztosítja ezt a létesítményt, de alternatív megoldásokhoz fordulhat.
int i{ 2 };
auto s{ std::to_wstring(i) }; // s is a std::wstring with value L"2".
A C++/WinRT winrt::to_hstring korlátozott számú típus esetén is támogatja. Túlterheléseket kell hozzáadnia minden további, szöveges formátumra alakítani kívánt típushoz.
| Nyelv | Stringify int | Enumeráció sztringgé alakítása |
|---|---|---|
| C# | string result = "hello, " + intValue.ToString();string result = $"hello, {intValue}"; |
string result = "status: " + status.ToString();string result = $"status: {status}"; |
| C++/WinRT | hstring result = L"hello, " + to_hstring(intValue); |
// must define overload (see below)hstring result = L"status: " + to_hstring(status); |
Egy enum string formátumba alakításakor meg kell adnia a winrt::to_hstringimplementációját.
namespace winrt
{
hstring to_hstring(StatusEnum status)
{
switch (status)
{
case StatusEnum::Success: return L"Success";
case StatusEnum::AccessDenied: return L"AccessDenied";
case StatusEnum::DisabledByPolicy: return L"DisabledByPolicy";
default: return to_hstring(static_cast<int>(status));
}
}
}
Ezeket a stringifikációkat gyakran implicit módon fogyasztja el az adatkötés.
<TextBlock>
You have <Run Text="{Binding FlowerCount}"/> flowers.
</TextBlock>
<TextBlock>
Most recent status is <Run Text="{x:Bind LatestOperation.Status}"/>.
</TextBlock>
Ezek a kötések a kötött tulajdonság winrt::to_hstring hajtják végre. A második példa (StatusEnum) esetében saját túlterhelést kell megadnia a winrt::to_hstring-hoz, ellenkező esetben fordítóhiba lép fel.
Lásd még Footer_Click metódusportolását.
Sztringépítés
A sztringépítéshez a C# a beépített StringBuilder típusát használja.
| Kategória | C# | C++/WinRT |
|---|---|---|
| Sztringépítés | StringBuilder builder;builder.Append(...); |
std::wostringstream builder;builder << ...; |
| Windows futtatókörnyezeti sztring hozzáfűzése a null értékek megőrzésével | builder.Append(s); |
builder << std::wstring_view{ s }; |
| Új vonal hozzáadása | builder.Append(Environment.NewLine); |
builder << std::endl; |
| Az eredmény elérése | s = builder.ToString(); |
ws = builder.str(); |
Lásd még a BuildClipboardFormatsOutputString metódusportolását, és a DisplayChangedFormats metódusportolását.
Kód futtatása a fő felhasználói felületi szálon
Ez a példa a vonalkódolvasó mintájából származik.
Ha egy C#-projekt fő felhasználói felületi szálán szeretne dolgozni, általában a CoreDispatcher.RunAsync metódust használja, ehhez hasonlóan.
private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// Do work on the main UI thread here.
});
}
Sokkal egyszerűbb ezt a C++/WinRT-ben kifejezni. Felhívjuk a figyelmét, hogy feltételezve, hogy az első felfüggesztési pont után (ebben az esetben a co_await) el akarjuk érni, érték szerint fogadjuk el a paramétereket. További információkért lásd: Paraméterátadás.
winrt::fire_and_forget Watcher_Added(DeviceWatcher sender, winrt::DeviceInformation args)
{
co_await Dispatcher();
// Do work on the main UI thread here.
}
Ha nem az alapértelmezett prioritáson kell elvégeznie a munkát, akkor tekintse meg a winrt::resume_foreground függvényt, amely túlterhelt, és prioritást vesz igénybe. A winrt::resume_foregroundhívásának várakoztatását bemutató kódokért tekintse meg a programozás szál-affinitás figyelembevételével.
A C++/WinRT-hez kapcsolódó portolással kapcsolatos feladatok
A saját futtatókörnyezeti osztályaik definiálása az IDL-ben
Lásd a(z) Főoldal típus, és konszolidálja a .idl fájlokat.
Adja meg a szükséges C++/WinRT Windows-névtérfejlécfájlokat
A C++/WinRT rendszerben, amikor windowsos névterekből szeretne típust használni, a megfelelő C++/WinRT Windows névtérfejlécfájlt kell tartalmaznia. Példa: A NotifyUser metódus portolása.
Dobozolás és kicsomagolás
A C# automatikusan a skaláris elemeket objektumokká alakítja. A C++/WinRT megköveteli a winrt::box_value függvény explicit meghívását. Mindkét nyelvben explicit módon kell kicsomagolni. Lásd: C++/WinRTdobozolása és kicsomagolása.
Az alábbi táblázatokban ezeket a definíciókat fogjuk használni.
| C# | C++/WinRT |
|---|---|
int i; |
int i; |
string s; |
winrt::hstring s; |
object o; |
IInspectable o; |
| Művelet | C# | C++/WinRT |
|---|---|---|
| Ökölvívás | o = 1;o = "string"; |
o = box_value(1);o = box_value(L"string"); |
| Kicsomagolás | i = (int)o;s = (string)o; |
i = unbox_value<int>(o);s = unbox_value<winrt::hstring>(o); |
A C++/CX és a C# kivételeket emel ki, ha null mutatót próbál meg egy értéktípusra kicsomaglni. A C++/WinRT ezt programozási hibának tekinti, és összeomlik. A C++/WinRT-ben használja a winrt::unbox_value_or függvényt, ha azt az esetet szeretné kezelni, amelyben az objektum nem az a típus, amelyről azt hitte.
| Forgatókönyv | C# | C++/WinRT |
|---|---|---|
| Ismert egész szám kicsomagolása | i = (int)o; |
i = unbox_value<int>(o); |
| Ha o null értékű | System.NullReferenceException |
Lezuhan |
| Ha az o nem egy dobozozott int | System.InvalidCastException |
Lezuhan |
| Az int kicsomagolása, tartalék használata null érték esetén; összeomlás, ha bármi más eset áll fenn | i = o != null ? (int)o : fallback; |
i = o ? unbox_value<int>(o) : fallback; |
| Ha lehetséges, csomagolja ki az int-et; használjon tartalék megoldást bármi más esetén | i = as int? ?? fallback; |
i = unbox_value_or<int>(o, fallback); |
Példaként lásd a OnNavigatedTo metódusának portolását, és a a Footer_Click metódusának portolását.
Boxing és unboxing egy szöveges adatsor
A sztringek valamilyen módon értéktípust, más módon pedig referenciatípust jelentek. A C# és a C++/WinRT eltérően kezeli a sztringeket.
Az ABI-típus HSTRING egy hivatkozással megszámolt sztringre mutató mutató. Ez azonban nem IInspectableszármazik, tehát technikailag nem objektum. Továbbá a null HSTRING az üres sztringet jelöli. Azoknak a dolgoknak a dobozolása, amelyek nem származnak az IInspectable származékaként, úgy történik, hogy azokat egy IReference<T>belsejében burkoljuk. A Windows futtatókörnyezet egy szabványos implementációt biztosít a PropertyValue objektum formájában (az egyéni típusokat a PropertyType::OtherTypenéven jelentik).
A C# egy Windows Futtatókörnyezet sztringet jelöl referenciatípusként; míg a C++/WinRT egy sztringet projektel értéktípusként. Ez azt jelenti, hogy a burkolt null sztringek különböző ábrázolásokkal rendelkezhetnek, attól függően, hogyan érkeztél el oda.
| Magatartás | C# | C++/WinRT |
|---|---|---|
| Nyilatkozatok | object o;string s; |
IInspectable o;hstring s; |
| Sztringtípus kategóriája | Hivatkozás típusa | Érték típusa |
| null HSTRING mint projektek | "" |
hstring{} |
Null és "" azonos? |
Nem | Igen |
| Null érték érvényessége | s = null;s.Length NullReferenceException értéket ad meg |
s = hstring{};s.size() == 0 (érvényes) |
| Ha null sztringet rendel az objektumhoz | o = (string)null;o == null |
o = box_value(hstring{});o != nullptr |
Ha ""-t hozzárendeli az objektumhoz |
o = "";o != null |
o = box_value(hstring{L""});o != nullptr |
Alapszintű bokszolás és kicsomagolás.
| Művelet | C# | C++/WinRT |
|---|---|---|
| Csomagolj be egy karakterláncot | o = s;Az üres sztring nem null értékű objektummá válik. |
o = box_value(s);Az üres sztring nem null értékű objektummá válik. |
| Ismert karakterlánc kicsomagolása | s = (string)o;A null objektum null sztring lesz. ÉrvénytelenCastException, ha nem string. |
s = unbox_value<hstring>(o);Null objektum összeomlik. Nem karakterlánc esetén összeomlik. |
| Egy lehetséges karakterlánc kicsomagolása | s = o as string;Null objektum vagy nem sztring null szöveggé válik. vagy s = o as string ?? fallback;A null vagy a nem karakterlánc alapértelmezett értékké válik. Üres sztring megőrzve. |
s = unbox_value_or<hstring>(o, fallback);A null vagy a nem karakterlánc alapértelmezett értékké válik. Üres sztring megőrzve. |
Osztály elérhetővé tétele a {Binding} korrektúrabővítmény számára
Ha a {Binding} jelöléskiterjesztést az adattípushoz való adatkötéshez szeretné használni, tekintse meg a {Binding}használatával deklarált kötésobjektumot.
Objektumok felhasználása XAML jelölőnyelvből
C#-projektben elérheti a XAML jelölés privát tagjait és elnevezett elemeit. A C++/WinRT rendszerben azonban az XAML-{x:Bind} jelölőbővítmény használata esetén minden entitást nyilvánosan közzé kell tenni az IDL-ben.
C#-ban a logikai értékek kötődése esetén a true vagy false jelenik meg, míg a C++/WinRT-ben a Windows.Foundation.IReference`1<logikai> formában.
További információért és példakódokért lásd: Objektumok használata a jelölőnyelvből.
Adatforrás hozzáférhetővé tétele a XAML-jelölés számára
A C++/WinRT 2.0.190530.8-es vagy újabb verziójában winrt::single_threaded_observable_vector egy megfigyelhető vektort hoz létre, amely támogatja IObservableVector<T> és IObservableVector<IInspectable>. Például lásd: a(z) Forgatókönyvek tulajdonság portolása.
A Midl-fájlt (.idl) ilyen módon hozhatja létre (lásd a Faktoring runtime osztályokat Midl-fájlokba (.idl)).
namespace Bookstore
{
runtimeclass BookSku { ... }
runtimeclass BookstoreViewModel
{
Windows.Foundation.Collections.IObservableVector<BookSku> BookSkus{ get; };
}
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
Így implementáljuk.
// BookstoreViewModel.h
...
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
{
BookstoreViewModel()
{
m_bookSkus = winrt::single_threaded_observable_vector<Bookstore::BookSku>();
m_bookSkus.Append(winrt::make<Bookstore::implementation::BookSku>(L"To Kill A Mockingbird"));
}
Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> BookSkus();
{
return m_bookSkus;
}
private:
Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> m_bookSkus;
};
...
További információ: XAML-elemek vezérlők; kötés C++/WinRT-gyűjteményhez, és C++/WinRT-gyűjteményekhez.
Adatforrás elérhetővé tétele az XAML-korrektúra számára (a C++/WinRT 2.0.190530.8 előtt)
Az XAML-adatkötés megköveteli, hogy egy elemforrás megvalósítsa IIterable<IInspectable>, valamint az alábbi illesztőkombinációk egyikét.
- IObservableVector<IInspectable>
- IBindableVector és INotifyCollectionChanged
- IBindableVector és IBindableObservableVector
- IBindableVector önmagában (nem reagál a változásokra)
- IVector<IInspectable>
- IBindableIterable (fog iterálni és elmenti az elemeket egy magángyűjteménybe)
A futásidejű környezetben nem észlelhető egy olyan általános interfész, mint a IVector<T>. Minden IVector<T> más interfészazonosítóval (IID) rendelkezik, amely Tfüggvénye. Bármely fejlesztő tetszőlegesen bővítheti a T készletét, így az XAML-kötési kód egyértelműen soha nem tudja a teljes lekérdezési készletet. Ez a korlátozás nem jelent problémát a C# esetében, mert minden olyan CLR-objektum, amely implementálja IEnumerable<T> automatikusan implementálja IEnumerable. Az ABI szintjén ez azt jelenti, hogy minden objektum, amely a IObservableVector<T>-t implementálja, automatikusan implementálja a IObservableVector<IInspectable>-t is.
A C++/WinRT nem biztosítja ezt a garanciát. Ha egy C++/WinRT futtatókörnyezeti osztály implementálja IObservableVector<T>, akkor nem feltételezhetjük, hogy a IObservableVector<IInspectable> implementációja is elérhető.
Következésképpen az előző példának így kell kinéznie.
...
runtimeclass BookstoreViewModel
{
// This is really an observable vector of BookSku.
Windows.Foundation.Collections.IObservableVector<Object> BookSkus{ get; };
}
És a megvalósítás.
// BookstoreViewModel.h
...
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
{
BookstoreViewModel()
{
m_bookSkus = winrt::single_threaded_observable_vector<Windows::Foundation::IInspectable>();
m_bookSkus.Append(winrt::make<Bookstore::implementation::BookSku>(L"To Kill A Mockingbird"));
}
// This is really an observable vector of BookSku.
Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> BookSkus();
{
return m_bookSkus;
}
private:
Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> m_bookSkus;
};
...
Ha hozzá kell férnie m_bookSkusobjektumaihoz, vissza kell adnia őket a Könyvesboltba::BookSku.
Widget MyPage::BookstoreViewModel(winrt::hstring title)
{
for (auto&& obj : m_bookSkus)
{
auto bookSku = obj.as<Bookstore::BookSku>();
if (bookSku.Title() == title) return bookSku;
}
return nullptr;
}
Származtatott osztályok
A futtatókörnyezeti osztályból való származtatáshoz az alaposztálynak összeállíthatókell lennie. C# nem követeli meg, hogy különleges lépéseket tegyen az osztályok komponálhatóvá tétele érdekében, de a C++/WinRT igen. A el nem zárt kulcsszóval jelzi, hogy a kívánt osztály alaposztályként használható.
unsealed runtimeclass BasePage : Windows.UI.Xaml.Controls.Page
{
...
}
runtimeclass DerivedPage : BasePage
{
...
}
A implementációs típushoz tartozó fejlécfájlban, először az alaposztály fejlécfájlját kell megadnia, mielőtt a származtatott osztály automatikusan generált fejlécét beillesztené. Ellenkező esetben olyan hibaüzenetek jelennek meg, mint például "Az ilyen típusú kifejezések tiltott használata".
// DerivedPage.h
#include "BasePage.h" // This comes first.
#include "DerivedPage.g.h" // Otherwise this header file will produce an error.
namespace winrt::MyNamespace::implementation
{
struct DerivedPage : DerivedPageT<DerivedPage>
{
...
}
}
Fontos API-k
Kapcsolódó témakörök
- C#-oktatóanyagok
- C++/WinRT
- Adatkötés részletes áttekintése