Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tavsiye
Bu konuyu daha önce okuduysanız ve belirli bir görevi göz önünde bulundurarak bu konuya geri dönüyorsanız, bu konunun Gerçekleştirmekte olduğunuz göreve göre içerik bul bölümüne atlayabilirsiniz .
Bu konu, bir C# projesindeki kaynak kodu C ++/WinRT'deki eşdeğerine taşımayla ilgili teknik ayrıntıları kapsamlı bir şekilde kataloglar.
Evrensel Windows Platformu (UWP) uygulama örneklerinden birini taşımaya yönelik örnek olay incelemesi için Pano örneğini C#'den C++/WinRT'ye taşıma konusuna bakın. Bu adım adım kılavuzu izleyip ilerledikçe örneği kendiniz uyarlayarak uyarlama pratiği ve deneyimi kazanabilirsiniz.
Nasıl hazırlanır ve ne bekleyebileceğiniz
Pano örneğini C#'den C++/WinRT'ye taşıma örnek incelemesi, bir projeyi C++/WinRT'ye taşırken yapacağınız yazılım tasarımı kararlarının örneklerini gösterir. Bu nedenle, mevcut kodun nasıl çalıştığı hakkında sağlam bir anlayış elde ederek taşımaya hazırlanmak iyi bir fikirdir. Bu şekilde, uygulamanın işlevselliğine ve kodun yapısına iyi bir genel bakış elde edersiniz ve ardından alacağınız kararlar sizi her zaman ileriye ve doğru yöne götürür.
Ne tür taşıma değişiklikleri bekleyebileceğinize göre, bunları dört kategoride gruplandırabilirsiniz.
-
Dil projeksiyonunu taşıma. Windows Çalışma Zamanı (WinRT) çeşitli programlama dillerine yansıtılır. Bu dil projeksiyonlarının her biri, ilgili programlama dilinde doğal ve dile özgü hissettirecek şekilde tasarlanmıştır. C# için bazı Windows Çalışma Zamanı türleri .NET türleri olarak yansıtılır. Örneğin, System.Collections.Generic.IReadOnlyList<T> öğesini tekrar Windows.Foundation.Collections.IVectorView<T> olarak çevireceksiniz. Ayrıca C# dilinde bazı Windows Çalışma Zamanı işlemleri uygun C# dil özellikleri olarak yansıtılır. C# dilinde olay işleme temsilcisini kaydetmek için işleç söz dizimini
+=kullanmanız buna örnek olarak verilmiştir. Bu nedenle, bunun gibi dil özelliklerini gerçekleştirilmekte olan temel işleme (bu örnekte olay kaydı) çevireceksiniz. -
Bağlantı noktası dili söz dizimi. Bu değişikliklerin çoğu basit mekanik dönüşümlerdir ve bir simgeyi başka bir simgeyle değiştirir. Örneğin, nokta (
.) değerini iki nokta üst üste (::) olarak değiştirme. -
Bağlantı noktası dili yordamı. Bunlardan bazıları basit, yinelenen değişiklikler olabilir (örneğin
myObject.MyProperty'danmyObject.MyProperty()'a). Diğerleri daha derin değişikliklere ihtiyaç duyar (örneğin, System.Text.StringBuilder'ın kullanımını içeren bir yordamı std::wostringstream kullanımını içeren bir yordama taşıma). -
C++/WinRT'ye özgü taşımayla ilgili görevler. Windows Çalışma Zamanı’ın bazı ayrıntıları, arka planda C# tarafından örtük olarak ele alınır. Bu ayrıntılar C++/WinRT'de açıkça yapılır. Örnek olarak çalışma zamanı sınıflarınızı tanımlamak için bir
.idldosya kullanmanız gerekir.
Sonraki görev tabanlı dizinden sonra, bu konudaki bölümlerin geri kalanı yukarıdaki taksonomiye göre yapılandırılır.
Gerçekleştirmekte olduğunuz göreve göre içerik bulma
| Görev | Content |
|---|---|
| Windows Çalışma Zamanı bileşeni (WRC) yazma | Belirli işlevler yalnızca C++ ile gerçekleştirilebilir (veya belirli API'ler çağrılabilir). Bu işlevi bir C++/WinRT WRC olarak hesaba katabilir ve ardından WRC'yi bir C# uygulamasından (örneğin) kullanabilirsiniz. Bkz.: C++/WinRT ile Windows Çalışma Zamanı bileşenleri ve bir Windows Çalışma Zamanı bileşeninde çalışma zamanı sınıfı oluşturuyorsanız. |
| Zaman uyumsuz yöntem taşıma | C++/WinRT çalışma zamanı sınıfındaki eşzamansız bir yöntemin ilk satırının auto lifetime = get_strong(); olması iyi bir fikirdir (bkz. Bir sınıf üyesi eş yordamında this işaretçisine güvenli bir şekilde erişme).Task öğesinden geçirme için bkz. Eşzamansız eylem.Task<T>'den taşıma, bkz. Eşzamansız işlem.async void konumundan taşıma için Fire-and-forget yöntemi bölümüne bakın. |
| Bir sınıfı taşıma | İlk olarak, sınıfın çalışma zamanı sınıfı olması gerekip gerekmediğini veya sıradan bir sınıf olup olmadığını belirleyin. Buna karar vermenize yardımcı olmak için C++/WinRT ile Yazar API'lerinin başlangıcına bakın. Ardından aşağıdaki sonraki üç satıra bakın. |
| Bir çalışma zamanı sınıfını uyarlama | C++ uygulamasının dışındaki işlevleri paylaşan bir sınıf veya XAML veri bağlamasında kullanılan bir sınıf. Bkz. bir Windows Çalışma Zamanı bileşeninde çalışma zamanı sınıfı yazıyorsanız veya XAML kullanıcı arabiriminizde başvurulan bir çalışma zamanı sınıfı yazıyorsanız. Bu bağlantılar bunu daha ayrıntılı olarak açıklar, ancak idl'de bir çalışma zamanı sınıfı bildirilmelidir. Eğer projeniz zaten bir IDL dosyası (örneğin, Project.idl) içeriyorsa, yeni bir çalışma zamanı sınıfını bu dosyada bildirmenizi öneririz. IDL'de, uygulamanızın dışında veya XAML'de kullanılacak tüm yöntemleri ve veri üyelerini bildirin. IDL dosyasını güncelledikten sonra yeniden derleyin ve projenizin Generated Files klasöründeki oluşturulan saplama dosyalarına (.h ve .cpp) bakın (Çözüm Gezgini'da, proje düğümü seçiliyken Tüm Dosyaları Göster seçeneğinin açık olduğundan emin olun). Saplama dosyalarını projenizde bulunan dosyalarla karşılaştırın, dosyaları ekleyin veya işlev imzalarını gerektiği şekilde ekleyin/güncelleştirin. Stub dosyasının sözdizimi her zaman doğrudur, bu nedenle derleme hatalarını en aza indirmek için bunu kullanmanızı öneririz. Projenizdeki taslaklar, taslak dosyalarındakilerle eşleştiğinde, devam edip bunları C# kodunu uyarlayarak hayata geçirebilirsiniz. |
| Sıradan bir sınıfı taşıyın | Bkz. Çalışma zamanı sınıfı yazmıyorsanız. |
| Yazar Kimliği |
Microsoft Arabirim Tanımı Dili 3.0'a Giriş XAML kullanıcı arayüzünüzde başvurulacak bir çalışma zamanı sınıfı yazarsanız XAML işaretlemesinden nesne kullanma IDL'de çalışma zamanı sınıflarınızı tanımlama |
| Koleksiyonu taşıma |
C++/WinRT ile Koleksiyonlar Veri kaynağını XAML işaretlemesi için kullanılabilir hale getirme İlişkili kapsayıcı Vektör üyesi erişimi |
| Olay taşıma |
Sınıf üyesi olarak olay işleyicisi temsilcisi Olay işleyici temsilcisini iptal etme |
| Bir yöntemi taşıma | C# dilinden: private async void SampleButton_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e) { ... }C++/WinRT .h dosyasına: fire_and_forget SampleButton_Tapped(IInspectable const&, RoutedEventArgs const&);C++/WinRT .cpp dosyasına: fire_and_forget OcrFileImage::SampleButton_Tapped(IInspectable const&, RoutedEventArgs const&) {...} |
| Bağlantı noktası dizeleri |
C++/WinRT'de dize işleme ToString Dize oluşturma Bir dizenin boxing ve unboxing işlemleri |
| Tür dönüştürme (tür atama) | C#: o.ToString()C++/WinRT: to_hstring(static_cast<int>(o))Ayrıca bkz. ToString. C#: (Value)oC++/WinRT: unbox_value<Value>(o)Kutu açma başarısız olursa atar. Ayrıca bkz. Boxing ve unboxing. C#: o as Value? ?? fallbackC++/WinRT: unbox_value_or<Value>(o, fallback)Unboxing başarısız olursa yedek değeri döndürür. Ayrıca bkz. Boxing ve unboxing. C#: (Class)oC++/WinRT: o.as<Class>()Dönüştürme başarısız olursa atar. C#: o as ClassC++/WinRT: o.try_as<Class>()Dönüştürme başarısız olursa null döndürür. |
Dil projeksiyonunu içeren değişiklikler
| Category | C# | C++/WinRT | Ayrıca bakınız |
|---|---|---|---|
| Yazılmamış nesne |
objectveya System.Object |
Windows::Foundation::IInspectable | EnableClipboardContentChangedNotifications yöntemini taşıma |
| Projeksiyon ad alanları | using System; |
using namespace Windows::Foundation; |
|
using System.Collections.Generic; |
using namespace Windows::Foundation::Collections; |
||
| Koleksiyonun boyutu | collection.Count |
collection.Size() |
BuildClipboardFormatsOutputString yöntemini taşıma |
| Tipik koleksiyon türü | Ilist<Bir öğe eklemek için T> ve Ekle'yi seçin. | Ivector<Bir öğe eklemek için T> ve Ekle'yi seçin. Herhangi bir yerde std::vector kullanıyorsanız, öğe eklemek için push_back . | |
| Yalnızca okunur koleksiyon türü | IReadOnlyList<T> | IVectorView<T> | BuildClipboardFormatsOutputString yöntemini taşıma |
| Sınıf üyesi olarak olay işleyici temsilcisi | myObject.EventName += Handler; |
token = myObject.EventName({ get_weak(), &Class::Handler }); |
EnableClipboardContentChangedNotifications yöntemini taşıma |
| Olay işleyici temsilcisini iptal etme | myObject.EventName -= Handler; |
myObject.EventName(token); |
EnableClipboardContentChangedNotifications yöntemini taşıma |
| İlişkisel kapsayıcı | IDictionary<K, V> | IMap<K, V> | |
| Vektör üye erişimi | x = v[i];v[i] = x; |
x = v.GetAt(i);v.SetAt(i, x); |
Olay işleyicisini kaydetme/iptal etme
C++/WinRT'de, C++/WinRT'de temsilcileri kullanarak olayları işleme bölümünde açıklandığı gibi bir olay işleyicisi temsilcisini kaydetmek/iptal etmek için çeşitli söz dizimsel seçenekleriniz vardır. Ayrıca EnableClipboardContentChangedNotifications yönteminin taşınması konusuna bakın.
Bazen, örneğin bir olay alıcısı (olayı işleyen bir nesne) yok edilmek üzere olduğunda, olay kaynağının (olayı oluşturan nesne) yok edilmiş bir nesneye çağrı yapmaması için bir olay işleyicisini iptal etmek istersiniz. Bkz. Kayıtlı temsilciyi iptal etme. Böyle durumlarda, olay işleyicileriniz için bir event_token üye değişkeni oluşturun. Örnek için bkz . EnableClipboardContentChangedNotifications yöntemini taşıma.
XAML işaretlemesinde bir olay işleyicisi de kaydedebilirsiniz.
<Button x:Name="OpenButton" Click="OpenButton_Click" />
C# dilinde, OpenButton_Click yönteminiz özel olabilir ve XAML bunu OpenButton tarafından oluşturulan ButtonBase.Click olayına bağlamaya devam edebilir.
C++/WinRT'de, OpenButton_Click yönteminiz, bunu XAML biçimlendirmesinde kaydetmek istiyorsanız, uygulama türünüzde public olmalıdır. Bir olay işleyicisini yalnızca kesinlik temelli koda kaydederseniz, olay işleyicisinin genel olması gerekmez.
namespace winrt::MyProject::implementation
{
struct MyPage : MyPageT<MyPage>
{
void OpenButton_Click(
winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& args);
}
};
Alternatif olarak, kayıt XAML sayfasını uygulama türünüzün bir arkadaşı yapabilir ve OpenButton_Click özel hale getirebilirsiniz.
namespace winrt::MyProject::implementation
{
struct MyPage : MyPageT<MyPage>
{
private:
friend MyPageT;
void OpenButton_Click(
winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& args);
}
};
Son senaryolardan biri, taşımakta olduğunuz C# projesinin işaretlemeden olay işleyicisine bağlandığı senaryodur (bu senaryo hakkında daha fazla arka plan için bkz. x:Bind'deki İşlevler).
<Button x:Name="OpenButton" Click="{x:Bind OpenButton_Click}" />
Bu işaretlemeyi daha basit Click="OpenButton_Click"olarak değiştirebilirsiniz. Ya da dilerseniz, o işaretlemeyi olduğu gibi bırakabilirsiniz. Bunu desteklemek için yapmanız gereken tek şey IDL'de olay işleyicisini bildirmektir.
void OpenButton_Click(Object sender, Microsoft.UI.Xaml.RoutedEventArgs e);
Note
İşlevi, onu Fire and forget olarak gerçekleştirseniz bile void olarak tanımlayın.
Dil söz dizimini içeren değişiklikler
| Category | C# | C++/WinRT | Ayrıca bakınız |
|---|---|---|---|
| Erişim değiştiricileri | public \<member\> |
public:\<member\> |
Button_Click yöntemini taşıma |
| Veri üyesine erişme | this.variable |
this->variable |
|
| Eşzamansız işlem | async Task ... |
IAsyncAction ... |
IAsyncAction arabirimi, C++/WinRT ile eşzamanlılık ve zaman uyumsuz işlemler |
| Eşzamansız işlem | async Task<T> ... |
IAsyncOperation<T> ... |
IAsyncOperation arabirimi, C++/WinRT ile eşzamanlılık ve zaman uyumsuz işlemler |
| Fire-and-forget yöntemi (asenkron olduğunu ifade eder) | async void ... |
winrt::fire_and_forget ... |
CopyButton_Click yöntemini taşıma, başlat ve unut |
| Numaralandırılmış sabite erişme | E.Value |
E::Value |
DisplayChangedFormats yöntemini taşıma |
| İşbirliğiyle bekleme | await ... |
co_await ... |
CopyButton_Click yöntemini taşıma |
| Özel alan olarak öngörülen türlerin koleksiyonu | private List<MyRuntimeClass> myRuntimeClasses = new List<MyRuntimeClass>(); |
std::vector<MyNamespace::MyRuntimeClass>m_myRuntimeClasses; |
|
| GUID oluşturma | 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} }; |
|
| Ad alanı ayırıcısı | A.B.T |
A::B::T |
|
| Null | null |
nullptr |
UpdateStatus yöntemini taşıma |
| Bir tip nesnesi alın | typeof(MyType) |
winrt::xaml_typename<MyType>() |
Senaryolar özelliğini taşıma |
| Bir yöntem için parametre bildirimi | MyType |
MyType const& |
Parametre aktarımı |
| Asenkron yöntem için parametre bildirimi | MyType |
MyType |
Parametre geçirme |
| Statik yöntem çağırma | T.Method() |
T::Method() |
|
| String'ler |
stringveya System.String |
winrt::hstring | C++/WinRT'de dize işleme |
| Karakter dizesi sabiti | "a string literal" |
L"a string literal" |
Yapıcıyı taşıma, Mevcut ve FEATURE_NAME |
| Çıkarılan (veya türetilen) tür | var |
auto |
BuildClipboardFormatsOutputString yöntemini taşıma |
| kullanma-yönergesi | using A.B.C; |
using namespace A::B::C; |
Oluşturucuyu taşıma, Geçerli ve FEATURE_NAME |
| Düz metin/ham dize değişmez değeri | @"verbatim string literal" |
LR"(raw string literal)" |
DisplayToast yöntemini taşıma |
Note
Bir başlık dosyası, belirli bir ad alanı için using namespace yönergesi içermiyorsa, bu ad alanındaki tüm tür adlarını tam adlarıyla belirtmeniz veya en azından derleyicinin onları bulabilmesi için yeterince nitelemeniz gerekir. Bir örnek için bkz. DisplayToast yönteminin taşınması.
Sınıfların ve üyelerin taşınması
Her C# türü için bunu bir Windows Çalışma Zamanı türüne mi yoksa normal bir C++ sınıfına/yapısına/numaralandırmasına mı taşımanız gerektiğine karar vermeniz gerekir. Daha fazla bilgi ve bu kararların nasıl alınıyor olduğunu gösteren ayrıntılı örnekler için bkz. Pano örneğini C# dilinden C++/WinRT'ye taşıma.
C# özelliği genellikle bir erişimci işlevi, bir mutator işlevi ve bir yedekleme veri üyesi olur. Daha fazla bilgi ve örnek için bkz. IsClipboardContentChangedEnabled özelliğini taşıma.
Statik olmayan alanlar için, bunları uygulama türünüzün veri üyeleri yapın.
C# statik alanı bir C++/WinRT statik erişimci ve/veya mutator işlevine dönüşür. Daha fazla bilgi ve örnek için bkz. Oluşturucuyu taşıma, Geçerli ve FEATURE_NAME.
Üye işlevleri için de her biri için IDL'ye ait olup olmadığına veya uygulama türünüzün genel veya özel üye işlevi olup olmadığına karar vermeniz gerekir. Daha fazla bilgi ve karar verme örnekleri için bkz. MainPage türü için IDL.
XAML işaretlemesini ve varlık dosyalarını taşıma
Pano örneğini C#'den C++/WinRT'ye taşıma durumunda, C# ve C++/WinRT projesinde aynı XAML işaretlemesini (kaynaklar dahil) ve varlık dosyalarını kullanabildik. Bazı durumlarda, bunu başarmak için işaretleme düzenlemeleri yapılması gerekir. Bkz. MainPage'i taşıma işlemini tamamlamak için gereken XAML ve stilleri kopyalama.
Dil içi prosedürleri içeren değişiklikler
| Category | C# | C++/WinRT | Ayrıca bakınız |
|---|---|---|---|
| Asenkron bir metotta yaşam süresi yönetimi | N/A |
auto lifetime{ get_strong() }; veyaauto lifetime = get_strong(); |
CopyButton_Click yöntemini taşıma |
| Elden çıkarma | using (var t = v) |
auto t{ v };t.Close(); // or let wrapper destructor do the work |
CopyImage yöntemini taşıma |
| Nesne oluşturma | new MyType(args) |
MyType{ args } veyaMyType(args) |
Senaryolar özelliğini taşıma |
| Başlatılmamış referans oluştur | MyType myObject; |
MyType myObject{ nullptr }; veyaMyType myObject = nullptr; |
Oluşturucuyu taşıma, Geçerli ve FEATURE_NAME |
| Args ile değişkene nesne oluşturma | var myObject = new MyType(args); |
auto myObject{ MyType{ args } }; veya auto myObject{ MyType(args) }; veya auto myObject = MyType{ args }; veya auto myObject = MyType(args); veya MyType myObject{ args }; veya MyType myObject(args); |
Footer_Click yöntemini taşıma |
| Argümansız olarak bir değişkende nesne oluşturma | var myObject = new T(); |
MyType myObject; |
BuildClipboardFormatsOutputString yöntemini taşıma |
| Nesne başlatma kısaltması | var p = new FileOpenPicker{ViewMode = PickerViewMode.List}; |
FileOpenPicker p;p.ViewMode(PickerViewMode::List); |
|
| Toplu vektör işlemi | var p = new FileOpenPicker{FileTypeFilter = { ".png", ".jpg", ".gif" }}; |
FileOpenPicker p;p.FileTypeFilter().ReplaceAll({ L".png", L".jpg", L".gif" }); |
CopyButton_Click yöntemini taşıma |
| Koleksiyon üzerinde dolaşma | foreach (var v in c) |
for (auto&& v : c) |
BuildClipboardFormatsOutputString yöntemini taşıma |
| Özel durumu yakala | catch (Exception ex) |
catch (winrt::hresult_error const& ex) |
PasteButton_Click yöntemini taşıma |
| Özel durum ayrıntıları | ex.Message |
ex.message() |
PasteButton_Click yöntemini taşıma |
| Bir özellik değerini alın | myObject.MyProperty |
myObject.MyProperty() |
NotifyUser yöntemini taşıma |
| Özellik değeri ayarlama | myObject.MyProperty = value; |
myObject.MyProperty(value); |
|
| Bir özellik değerini artırın | myObject.MyProperty += v; |
myObject.MyProperty(thing.Property() + v);Dizeler için oluşturucuya geçin |
|
| ToString() | myObject.ToString() |
winrt::to_hstring(myObject) |
ToString() |
| dil dizesinden Windows Çalışma Zamanı dizesine | N/A | winrt::hstring{ s } |
|
| Dize oluşturma | StringBuilder builder;builder.Append(...); |
std::wostringstream builder;builder << ...; |
Dize oluşturma |
| Dize enterpolasyonu | $"{i++}) {s.Title}" |
winrt::to_hstring ve/veya winrt::hstring::operator+ | OnNavigatedTo yöntemini taşıma |
| Karşılaştırma için boş dize | System.String.Empty | winrt::hstring::empty | UpdateStatus yöntemini taşıma |
| Boş dize oluşturma | var myEmptyString = String.Empty; |
winrt::hstring myEmptyString{ L"" }; |
|
| Sözlük işlemleri | 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ür dönüştürme (başarısızlıkta hata fırlatır) | (MyType)v |
v.as<MyType>() |
Footer_Click yöntemini taşıma |
| Tür dönüştürme (başarısız olursa null) | v as MyType |
v.try_as<MyType>() |
PasteButton_Click yöntemini taşıma |
| x:Name’e sahip XAML öğeleri özelliklerdir | MyNamedElement |
MyNamedElement() |
Oluşturucuyu taşıma, Geçerli ve FEATURE_NAME |
| UI iş parçacığına geçin | CoreDispatcher.RunAsync | DispatcherQueue.TryEnqueue veya winrt::resume_foreground | NotifyUser yöntemini taşıma ve HistoryAndRoaming yöntemini taşıma |
| XAML sayfasındaki kesinlik temelli kodda UI öğesi oluşturma | Bkz . UI öğesi oluşturma | Bkz . UI öğesi oluşturma |
Aşağıdaki bölümlerde tablodaki bazı öğelerle ilgili daha ayrıntılı bilgi ve bulabilirsiniz.
UI öğesi oluşturma
Bu kod örnekleri, XAML sayfasının kesinlik temelli kodunda ui öğesinin oluşturulmasını gösterir.
var myTextBlock = new TextBlock()
{
Text = "Text",
Style = (Microsoft.UI.Xaml.Style)this.Resources["MyTextBlockStyle"]
};
TextBlock myTextBlock;
myTextBlock.Text(L"Text");
myTextBlock.Style(
winrt::unbox_value<Microsoft::UI::Xaml::Style>(
Resources().Lookup(
winrt::box_value(L"MyTextBlockStyle")
)
)
);
ToString()
C# türleri Object.ToString yöntemini sağlar.
int i = 2;
var s = i.ToString(); // s is a System.String with value "2".
C++/WinRT bu tesisi doğrudan sağlamaz, ancak alternatiflere dönebilirsiniz.
int i{ 2 };
auto s{ std::to_wstring(i) }; // s is a std::wstring with value L"2".
C++/WinRT sınırlı sayıda tür için winrt::to_hstring'i de destekler. Dizeleştirmek istediğiniz ek türler için aşırı yüklemeler eklemeniz gerekir.
| Language | int'i dizgeye dönüştür | enum'u dizeye dönüştürme |
|---|---|---|
| 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); |
Bir enum’u dizeye dönüştürme söz konusu olduğunda, winrt::to_hstring gerçeklemesini sağlamanız gerekir.
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));
}
}
}
Bu dizeleştirmeler genellikle veri bağlama tarafından örtük olarak kullanılır.
<TextBlock>
You have <Run Text="{Binding FlowerCount}"/> flowers.
</TextBlock>
<TextBlock>
Most recent status is <Run Text="{x:Bind LatestOperation.Status}"/>.
</TextBlock>
Bu bağlamalar, ilişkili özelliğin winrt::to_hstring işlemini gerçekleştirir. İkinci örnekte ( StatusEnum) kendi winrt::to_hstring aşırı yüklemesini sağlamanız gerekir, aksi takdirde derleyici hatası alırsınız.
Ayrıca Footer_Click yöntemini taşıma konusuna bakın.
Dize oluşturma
Dize derleme için C# yerleşik bir StringBuilder türüne sahiptir.
| Category | C# | C++/WinRT |
|---|---|---|
| Dize oluşturma | StringBuilder builder;builder.Append(...); |
std::wostringstream builder;builder << ...; |
| null değerleri koruyarak bir Windows Çalışma Zamanı dizesi ekleyin | builder.Append(s); |
builder << std::wstring_view{ s }; |
| Yeni satır ekleme | builder.Append(Environment.NewLine); |
builder << std::endl; |
| Sonuda erişme | s = builder.ToString(); |
ws = builder.str(); |
Ayrıca bkz. BuildClipboardFormatsOutputString yönteminin taşınması ve DisplayChangedFormats yönteminin taşınması.
Ana kullanıcı arabirimi iş parçacığında kod çalıştırma
Bu örnek Barkod tarayıcı örneğinden alınmıştır.
C# projesindeki ana kullanıcı arabirimi iş parçacığı üzerinde çalışmak istediğinizde, genellikle DispatcherQueue.TryEnqueue yöntemini (veya UWP'de eski CoreDispatcher.RunAsync'i ) kullanırsınız. C# dilinde desen aşağıdaki gibi görünür.
private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)
{
DispatcherQueue.TryEnqueue(() =>
{
// Do work on the main UI thread here.
});
}
Bunu C++/WinRT ile ifade etmek çok daha kolaydır. İlk askıya alma noktasından (bu örnekte) sonra bunlara erişmek istediğimiz varsayımı üzerine parametreleri değere göre kabul ettiğimize co_awaitdikkat edin. Daha fazla bilgi için bkz. Parametre geçirme.
winrt::fire_and_forget Watcher_Added(DeviceWatcher sender, winrt::DeviceInformation args)
{
co_await DispatcherQueue();
// Do work on the main UI thread here.
}
İşi varsayılan dışında bir öncelikte yapmanız gerekiyorsa, öncelik parametresi alan bir aşırı yüklemesi bulunan winrt::resume_foreground işlevine bakın. winrt::resume_foreground çağrısının nasıl await edileceğini gösteren kod örnekleri için bkz: İş parçacığı yakınlığını göz önünde bulundurarak programlama.
C++/WinRT'ye özgü taşımayla ilgili görevler
IDL'de çalışma zamanı sınıflarınızı tanımlama
MainPage türü için IDL'ye bakın ve .idl dosyalarınızı birleştirin.
İhtiyacınız olan C++/WinRT Windows ad alanı üst bilgi dosyalarını ekleyin
C++/WinRT'de, bir Windows ad alanından tür kullanmak istediğinizde, ilgili C++/WinRT Windows ad alanı üst bilgi dosyasını eklemeniz gerekir. Bir örnek için bkz. NotifyUser yöntemini taşıma.
Kutulama ve kutu açma
C#, skaler değerleri otomatik olarak object türüne kutular. C++/WinRT, winrt::box_value işlevini açıkça çağırmanızı gerektirir. Her iki dil de kutudan çıkarmayı açıkça belirtmenizi gerektirir. Bkz. C++/WinRT ile kutulama ve kutu açma.
Aşağıdaki tablolarda bu tanımları kullanacağız.
| C# | C++/WinRT |
|---|---|
int i; |
int i; |
string s; |
winrt::hstring s; |
object o; |
IInspectable o; |
| Operation | C# | C++/WinRT |
|---|---|---|
| Boks | o = 1;o = "string"; |
o = box_value(1);o = box_value(L"string"); |
| Kutudan çıkarma | i = (int)o;s = (string)o; |
i = unbox_value<int>(o);s = unbox_value<winrt::hstring>(o); |
C++/CX ve C# bir değer türüne null işaretçisini kaldırmaya çalışırsanız özel durumlar oluşturur. C++/WinRT bunu programlama hatası sayar ve çöker. C++/WinRT'de winrt::unbox_value_or işlevini kullanarak nesnenin sandığınız türde olmadığı bir durumla ilgilenmek isteyebilirsiniz.
| Scenario | C# | C++/WinRT |
|---|---|---|
| Bilinen bir tamsayının kutudan çıkarılması | i = (int)o; |
i = unbox_value<int>(o); |
| o null ise | System.NullReferenceException |
Çökme |
| o, kutulanmış bir int değilse | System.InvalidCastException |
Çökme |
| int’in kutusunu aç, null ise yedeği kullan; başka bir şeyse çök | i = o != null ? (int)o : fallback; |
i = o ? unbox_value<int>(o) : fallback; |
| Mümkünse int kutusunu aç; diğer her şey için geri dönüş kullan | i = as int? ?? fallback; |
i = unbox_value_or<int>(o, fallback); |
Örnek için OnNavigatedTo yöntemini taşıma ve Footer_Click yöntemini taşıma bölümlerine bakın.
Dizeyi kutulama ve kutulama
Dize, bazı yönlerden bir değer türü ve diğer şekillerde bir başvuru türüdür. C# ve C++/WinRT dizeleri farklı şekilde ele alır.
ABI türü HSTRING, başvuru sayısı tutulan bir dizenin işaretçisidir. Ancak IInspectable'dan türetilmez, bu nedenle teknik olarak bir nesne değildir. Ayrıca, null HSTRING boş dizeyi temsil eder. IInspectable'dan türetilmeyen öğelerin kutulanması, bunları bir IReference<T> içine sarmalayarak yapılır ve Windows Çalışma Zamanı PropertyValue nesnesi biçiminde standart bir uygulama sağlar (özel türler PropertyType::OtherType olarak bildirilir).
C#, bir Windows Çalışma Zamanı dizesini referans türü olarak temsil ederken, C++/WinRT Windows Çalışma Zamanı dizesini değer türü olarak ele alır. Bu, kutulanmış null dizenin oraya nasıl girdiğinize bağlı olarak farklı gösterimleri olabileceği anlamına gelir.
| Behavior | C# | C++/WinRT |
|---|---|---|
| Bildirim | object o;string s; |
IInspectable o;hstring s; |
| Dize türü kategorisi | Referans türü | Değer türü |
| null HSTRING olarak yansıtılır | "" |
hstring{} |
Null ve "" özdeş mi? |
No | Yes |
| Null değerinin geçerliliği | s = null;s.Length NullReferenceException oluşturur |
s = hstring{};s.size() == 0 (geçerli) |
| Nesneye null dize atarsanız | o = (string)null;o == null |
o = box_value(hstring{});o != nullptr |
"" nesneye atarsanız |
o = "";o != null |
o = box_value(hstring{L""});o != nullptr |
Temel kutulama ve kutu açma.
| Operation | C# | C++/WinRT |
|---|---|---|
| Dizeyi kutu içine al | o = s;Boş dize null olmayan nesneye dönüşür. |
o = box_value(s);Boş dize null olmayan nesneye dönüşür. |
| Bilinen bir dizeyi kutudan çıkarma | s = (string)o;Null nesne null dizeye dönüşür. Dize değilse InvalidCastException oluşur. |
s = unbox_value<hstring>(o);Null nesne çöküyor. Dize değilse çöküyor. |
| Olası bir dizenin kutusunu kaldırma | s = o as string;Null nesne veya dize olmayan değer, null dizeye dönüşür. OR s = o as string ?? fallback;Null veya dize olmayan geri dönüş olur. Boş dize korunur. |
s = unbox_value_or<hstring>(o, fallback);Null veya string olmayan değer, varsayılan değer olarak kullanılır. Boş dize korunur. |
Bir sınıfı {Binding} işaretleme uzantısı için kullanılabilir hale getirme
Veri türünüzle veri bağlamak için {Binding} işaretleme uzantısını kullanmayı planlıyorsanız bkz. {Binding} kullanılarak bildirilen Bağlama nesnesi.
XAML biçimlendirmesinden nesneleri kullanma
C# projesinde, XAML işaretlemesindeki özel üyeleri ve adlandırılmış öğeleri kullanabilirsiniz. Ancak C++/WinRT'de, XAML {x:Bind} işaretleme uzantısı kullanılarak kullanılan tüm varlıklar IDL'de genel kullanıma sunulmalıdır.
Ayrıca, bir Boolean türüne bağlama C#’ta true veya false olarak görüntülenir, ancak C++/WinRT’de Windows.Foundation.IReference`1<Boolean> olarak gösterilir.
Daha fazla bilgi ve kod örnekleri için, İşaretlemeden nesneleri kullanma bölümüne bakın.
Veri kaynağını XAML işaretlemesi için kullanılabilir hale getirme
C++/WinRT sürüm 2.0.190530.8 veya sonraki sürümlerinde winrt::single_threaded_observable_vector, hem IObservableVector T< hem de IObservableVector ><IInspectable'ı> destekleyen gözlemlenebilir bir vektör oluşturur. Bir örnek için bkz. Scenarios özelliğinin taşınması.
Midl dosyanızı (.idl) şu şekilde yazabilirsiniz (ayrıca bkz. Çalışma zamanı sınıflarını Midl dosyalarına ayırma (.idl)).
namespace Bookstore
{
runtimeclass BookSku { ... }
runtimeclass BookstoreViewModel
{
Windows.Foundation.Collections.IObservableVector<BookSku> BookSkus{ get; };
}
runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
Ve bu şekilde uygulayın.
// 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;
};
...
Daha fazla bilgi için bkz . XAML öğeleri denetimleri; C++/WinRT koleksiyonuna bağlama ve C++/WinRT ile Koleksiyonlar.
Bir veri kaynağını XAML işaretlemesi için kullanılabilir hale getirme (C++/WinRT 2.0.190530.8'den önce)
XAML veri bağlama, bir öğe kaynağının IIterable<IInspectable> uygulamasını ve aşağıdaki arabirim birleşimlerinden birini gerçekleştirmesini gerektirir.
- IObservableVector<IInspectable>
- IBindableVector ve INotifyCollectionChanged
- IBindableVector ve IBindableObservableVector
- IBindableVector tek başına (değişikliklere yanıt vermez)
- IVector<IInspectable>
- IBindableIterable (öğeleri yineler ve özel koleksiyona kaydeder)
IVector<T> gibi genel bir arabirim çalışma zamanında algılanamaz. Her IVector<T'nin> bir işlevi olan farklı bir arabirim tanımlayıcısı (IID) vardır. Herhangi bir geliştirici T kümesini rastgele genişletebilir, bu nedenle açıkça XAML bağlama kodu sorgu için tam kümeyi asla bilemez. IEnumerable T< uygulayan her CLR nesnesi otomatik olarak IEnumerable> uyguladığından bu kısıtlama C# için sorun değildir. ABI düzeyinde bu, IObservableVector T< uygulayan her nesnenin IObservableVector><IInspectable'ı> otomatik olarak uyguladığı anlamına gelir.
C++/WinRT bu garantiyi sunmaz. C++/WinRT çalışma zamanı sınıfı IObservableVector<T> uyguluyorsa, IObservableVector<IInspectable> uygulamasının da bir şekilde sağlandığını varsayamayız.
Sonuç olarak, önceki örneğin nasıl görünmesi gerektiği aşağıda verilmiştir.
...
runtimeclass BookstoreViewModel
{
// This is really an observable vector of BookSku.
Windows.Foundation.Collections.IObservableVector<Object> BookSkus{ get; };
}
Ve uygulama.
// 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;
};
...
m_bookSkus nesnelere erişmeniz gerekiyorsa, bunları Bookstore::BookSku'ya geri döndürmeniz gerekir.
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;
}
Türetilmiş sınıflar
Çalışma zamanı sınıfından türetmek için temel sınıfın birleştirilebilir olması gerekir. C# sınıflarınızı birleştirilebilir hale getirmek için herhangi bir özel adım atmanızı gerektirmez, ancak C++/WinRT yapar. Sınıfınızın temel sınıf olarak kullanılabilir olmasını istediğinizi belirtmek için korumasız anahtar sözcüğünü kullanırsınız.
unsealed runtimeclass BasePage : Microsoft.UI.Xaml.Controls.Page
{
...
}
runtimeclass DerivedPage : BasePage
{
...
}
Uygulama türünüzün üst bilgi dosyasına, türetilmiş sınıf için otomatik olarak oluşturulan üst bilgiyi eklemeden önce temel sınıf üst bilgi dosyasını eklemeniz gerekir. Aksi takdirde "Bu türün ifade olarak geçersiz kullanımı" gibi hatalar alırsınız.
// 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>
{
...
}
}
Önemli API'ler
İlgili konular
Windows developer