ãã®èšäºã§ã¯ãã¯ãã¹ãã©ãããã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã.NET CoreãšAvaloniaã«å®è£ ããæ¹æ³ã説æããŸãã TelegramããŒãã¯æè¿éåžžã«äººæ°ããããŸã-ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ãäœæããããšã¯ããèå³æ·±ããã®ã«ãªããŸãã
ãã®èšäºã¯ãAvaloniaã§ã®ããªãåºæ¬çãªéçºã³ã³ã»ãããã«ããŒããŠããŸãã ãã ãããHelloãWorldãã¯äœæããŸããã 代ããã«ãå®éã®ã¢ããªã±ãŒã·ã§ã³ãæ€èšããããšãææ¡ãããŠããŸãã ã¢ããªã±ãŒã·ã§ã³ã®äžè¬çãªã¢ãŒããã¯ãã£ãšåã ã®ã³ã³ããŒãã³ãã®äž¡æ¹ãåŠç¿ããŸãã
èªè ã®æ³šæãä¹±ããªãããã«ãå Žåã«ãã£ãŠã¯ã詳现ãæèçã«çç¥ããŠã説æãšå®è£ ãç°¡çŽ åããå¿ èŠããããŸãã å®éã®ã³ãŒãã¯ãåžžã«GitHubã§è¡šç€ºã§ããŸã ã
èšäºã®ããã¹ãã¯æ¬è³ªçã«æè²çã§ããããããžã§ã¯ãèªäœã¯éåžžã«çŸå®çã§ãã ãããžã§ã¯ãã®ç®çã¯ãäœæ¥ããŒã«ãšããŠäœ¿çšããããã«èšèšãããã¯ã©ã€ã¢ã³ããäœæããããšã§ãã å€ãã®ã¢ã€ãã¢ã¯ä»ã®ã¡ãã»ã³ãžã£ãŒããåçšãããTelegramã¢ãã«ã«è»¢éãããŸãã
ãã®ãããžã§ã¯ãã¯éçºäžã§ãããçŸåšãæ¥åžžã®äœ¿çšã«ã¯é©ããŠããŸããã ç¹ã«ãèè ã¯ãå¿ãåãããã人ã ããã®èšäºã®éçºã«åŒãä»ããããšãæåŸ ããŠããŸãã
ã¯ããã«
ç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã¯ãAvaloniaãã¬ãŒã ã¯ãŒã¯ã«åºã¥ããŠããŸãã MVVMããã³Rx.NETãã¿ãŒã³ãç©æ¥µçã«äœ¿çšããŸãã XAMLã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãæ§ç¯ããããã®ããŒã¯ã¢ããèšèªãšããŠäœ¿çšãããŸãã Telegram APIãšéä¿¡ããããã«ãTDLibã©ã€ãã©ãªãš.NETçšã®èªåçæããããã€ã³ããŒã䜿çšãããŸãã
ãªã¢ã¯ãã£ãããã°ã©ãã³ã°ã¯ãéçºã§åºã䜿çšãããŸãã äžè¬ã«ãã¢ããªã±ãŒã·ã§ã³ã¯ææ°ã®UIãã¬ãŒã ã¯ãŒã¯ã§æ¡çšãããŠããã¢ãããŒãã«åŸããŸãã WPFã«ç²ŸéããŠããå ŽåãAvaloniaãžã®ã¢ããã°ã¬ãŒãã¯æ¯èŒçç°¡åã§ãã React.jsã®ãããªãã®ãç¥ãããšãã害ãäžããããšã¯ãããŸããã
Avaloniaã¯ãç¹å®ã®ãã©ãããã©ãŒã ã«åºæã®éçºè å®è£ ã®è©³çŽ°ãé ããŠããŸãã ããã°ã©ãã¯éåžžããããã¬ãã«ã®ã³ã³ããŒãã³ããæ±ããŸãã ãããã£ãŠãããšãã°ãæ°ããã¢ããªã±ãŒã·ã§ã³ãäœæããã«ã¯ãAvaloniaãAvalonia.Desktopããã±ãŒãžãã€ã³ã¹ããŒã«ããMainé¢æ°ã«æ¬¡ã®è¡ãèšè¿°ããå¿ èŠããããŸãã
AppBuilder .Configure(new App()) .UsePlatformDetect() .UseReactiveUI() .Start<MainWindow>(() => context);
ããã¯å žåçãªBuilderã§ããã.NET Coreããã³ASP.NET Coreãæ±ã£ããã¹ãŠã®äººã«ããç¥ãããŠããŸãã ããŒã©ã€ã³ã¯UsePlatformDetectã§ãã Avaloniaã¯ãããã°ã©ã ãå®è¡ãããç°å¢ã®æ±ºå®ãåŒãåããUIãã¬ã³ããªã³ã°ããããã®ããã¯ãšã³ããæ§æããŸãã ããã§ã®AppãšMainWindowã¯ãããããAvalonia.ApplicationãšAvalonia.Windowããç¶æ¿ãããã¯ã©ã¹ã§ããããããã®ç®çã¯ååããã»ãŒæ確ã§ããå¿ èŠããããŸããåŸã§æ»ããŸãã
VisualStudioã®æ¡åŒµæ©èœã䜿çšããå Žåããããã®ã¯ã©ã¹ã®å®è£ ãå«ããã³ãã¬ãŒããæäŸãããŸãã æ¡åŒµæ©èœã䜿çšããŠãããžã§ã¯ããäœæããŸãããã ãããžã§ã¯ãã«ã¯æ¬¡ã®ãã¡ã€ã«ãå«ãŸããããšãããããŸãã
./App.xaml ./App.xaml.cs ./MainWindow.xaml ./MainWindow.xaml.cs
ã芧ã®ãšããããããã¯AppãšMainWindowã®åãã¯ã©ã¹ã§ãããåè¿°ã®ãšãããXAMLãã¡ã€ã«ã§è£è¶³ãããŠããŸãã ãããã®åã¯ã©ã¹ã«ã¯ãAvaloniaXamlLoader.LoadïŒthisïŒãšããåŒã³åºããå«ãŸããŸãã ããã§ã¯è©³ãã説æããŸããããã®ã¡ãœããã¯ãåãååã®XAMLãã¡ã€ã«ãèªã¿èŸŒã¿ãããã.NETãªããžã§ã¯ãã«å€æããŠãåŒæ°ãšããŠæž¡ãããã¿ãŒã²ãããªããžã§ã¯ãããåããããšããã ãã§ãã
XAMLã®è©³çŽ°ãç解ããå¿ èŠãããå Žåã¯ãä»ã®ãœãŒã¹ããããããååŸã§ããŸã-WPFã®æ¬ãªãã©ãã§ãã§ããŸãã åçŽãªã±ãŒã¹ã§ã¯ãããã¯å¿ èŠã§ã¯ãããŸãããAvaloniaãããã«æäŸããã³ã³ããŒãã³ãã®äœ¿çšæ¹æ³ãåŠç¿ããã ãã§ååã§ãã
åæ§ã«ãAvaloniaã¯å®è£ ããã³å¶åŸ¡ïŒè¡šç€ºïŒããŸãã XAMLãã¡ã€ã«ã¯ãéå±€ã宣èšçã«èšè¿°ããã¢ããªã±ãŒã·ã§ã³ã®ã¡ã¢ãªå ã®éåžžã®ãªããžã§ã¯ãã«å€æããããã«æ¬è³ªçã«å¿ èŠã§ãã ãã®ãããªéå±€ã®äŸãšããŠããã©ãŒã ã«åã蟌ãŸãããã¿ã³ããããŸãããã®ãã¿ã³ã¯ããŠã£ã³ããŠå ã«é 眮ãããŠããŸãã
<Window> <Panel> <Button> <TextBlock>Foo Bar</TextBlock> </Button> </Panel> </Window>
Avaloniaã«ã¯ãTextBlockãButtonãImageãªã©ã®å®çŸ©æžã¿ã®ã³ã³ãããŒã«ã»ãããå«ãŸããŠããŸãã ããè€éãªæ§é ãžã®æ§æã«ã¯ãã°ãªãããããã«ããªã¹ãããã¯ã¹ãªã©ã®ã³ã³ãããŒã«ã³ã³ãããŒã䜿çšãããŸãã ãããã®ãã¹ãŠã®ã³ã³ãããŒã«ã¯ãWPFã§ã®å®è£ æ¹æ³ãšåæ§ã«æ©èœããŸããã€ãŸããå©çšå¯èœãªããã¥ã¡ã³ãããããã§ããã«ãããããããã»ãšãã©ã®å ŽåãWPFã®ãããªã¢ã«ã䜿çšããããšãå¯èœã§ãã
MVVMã®å®è£
ã¢ããªã±ãŒã·ã§ã³ãšãã®è¡šç€ºã®å éšç¶æ ãåé¢ããããšããŸãã ç¶æ ã¯ããªããžã§ã¯ãã®ç¹å®ã®éå±€ïŒãã¥ãŒã¢ãã«ïŒã«ä¿åãããŸãã ãã¥ãŒã¯ããã¥ãŒã¢ãã«ã®å€æŽã«å¿çããUIãåæ§ç¯ããŸãã ãŸãããã¥ãŒã¢ãã«ã¯ããŠãŒã¶ãŒã€ãã³ããŸãã¯å€éšã€ãã³ããšãã2ã€ã®èŠå ã®åœ±é¿äžã§å€æŽã§ããããã«ãªããŸãã ãã¿ã³ãã¯ãªãã¯ããããšã¯Viewã®ã«ã¹ã¿ã ã€ãã³ãã®äŸã§ãããæ°ãããã£ããã¡ãã»ãŒãžã¯å€éšã€ãã³ãã§ãã
Avaloniaã§ã¯ããã¥ãŒã¢ãã«ã¯ããŒã¿ã³ã³ããã¹ããŸãã¯åã«ãã³ã³ããã¹ãããšããçšèªãšå¯æ¥ã«ãªã³ã¯ããŠããŸãã ãã¹ãŠã®æŠå¿µãåãæå³ã§äœ¿çšããŸãã
ãã¥ãŒã¢ãã«ã®éå±€ã¯ãå€ãã®å Žåãå°ãªããšãæåã®è¿äŒŒã§ã¯ãã¥ãŒæ§é ã«äŒŒãŠããŸãã Viewãå®å šã«Avaloniaã®å¶åŸ¡ãã€ãŸã ã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯ãç¶æ ã管çããŸãããããã®å€æŽã«å¯Ÿå¿ããã€ã³ã¿ãŒãã§ã€ã¹ãåæç»ããã®ã¯ãã¬ãŒã ã¯ãŒã¯ã®è²¬ä»»ã§ãã
ãã¥ãŒã¢ãã«ã®æäžäœæ§é ã¯æ¬¡ã®ããã«ãªããŸãïŒæ¬äŒŒã³ãŒãïŒã
App { ... Index # int ... Auth { ... Phone # string Password # string } Main { Nav { ... Contacts # ReactiveList<Contact> } Chat { ... Messages # ReactiveList<Message> } } }
芪ã³ã³ããã¹ãã¯ãåã³ã³ããã¹ãã®ã©ã€ããµã€ã¯ã«ã管çããŸãããã®è²¬ä»»ã¯ããã¹ããããã³ã³ããã¹ããäœæããã³è§£æŸããããšã§ãã ã«ãŒãDataContextã¯ãMainWindowãªããžã§ã¯ãã®äœææã«Builderã«æž¡ããïŒäžèšåç §ïŒãå°æ¥çã«ã¯ãã¥ãŒã¢ãã«éå±€å šäœã管çããŸãã
ãã¥ãŒã¯ããã€ã³ãã£ã³ã°ã¡ã«ããºã ãä»ããŠãã¹ããããã³ã³ãããŒã«ã®ã³ã³ããã¹ããèšå®ããŸãã å®éã«ã¯ãããã¯ãªããžã§ã¯ãã®ããããã£ã®å€ãèšå®ãããã®å€æŽããµãã¹ã¯ã©ã€ãããããã«å¿ èŠã§ãã
ãžã§ãã§ã®ãã€ã³ããŒã®äœ¿çšæ¹æ³ã«æ³šæããŠãã ããã
- ã«ã«ãŒã»ã«ã³ã³ãããŒã«ã®SelectedIndexã®ããããã£ïŒã¢ããªã±ãŒã·ã§ã³ã衚瀺ããããŒãžã決å®-æ¿èªãã©ãŒã ãŸãã¯ãã£ããïŒ
- TextBoxã®ããã¹ãããããã£ïŒã¢ãã«ã®å€ãé»è©±çªå·ãšãã¹ã¯ãŒãå ¥åãã©ãŒã ã®ããã¹ãã«é¢é£ä»ããŸãïŒ
- ãã¹ãŠã®ãã¹ããããã³ã³ããã¹ã
<Window DataContext="{Binding App}"> <Carousel SelectedIndex="{Binding Index}"> <Panel DataContext="{Binding Auth}"> <TextBox Text="{Binding Phone, Mode=TwoWay}" /> <TextBox Text="{Binding Password, Mode=TwoWay}" /> </Panel> <Grid DataContext="{Binding Main}"> <Panel DataContext="{Binding Nav}"> <ListBox Items="{Binding Contacts}" /> </Panel> <Panel DataContext="{Binding Chat}"> <ListBox Items="{Binding Messages}" /> </Panel> </Grid> </Carousel> </Window>
ãã®äŸã§ã¯ãAppContextã«ã¯ãMainContextãšAuthContextã®2ã€ã®åã³ã³ããã¹ããå«ãŸããŠããŸãã AppContextã¯ããã¹ããããã³ã³ããã¹ãã®ã©ã€ããµã€ã¯ã«ã管çããŸãïŒã³ã³ããã¹ãã®åæåãšè§£æŸãè¡ããŸãã
å®éã«ã¯ã次ã®ããã«ãªããŸããã¢ããªã±ãŒã·ã§ã³ã®èµ·ååŸãAppContextã¯ãŠãŒã¶ãŒãæ¿èªãããŠãããã©ããã確èªããæ¿èªãããŠããªãå Žåã¯åAuthContextãåæåããŸãã ã¢ããªã±ãŒã·ã§ã³ã®GUIã¯ãAuthContextã®äœæã«å¿çããŠãæ¿èªãã©ãŒã ã衚瀺ããŸãã ãŠãŒã¶ãŒã¯è³æ Œæ å ±ãå ¥åãããã°ã€ã³ããæ¿èªã€ãã³ãçšã«AppContextã«çœ²åããAuthContextããªãªãŒã¹ãããšåæã«MainContextãåæåããŸãã SelectedIndexã¯0ãã1ã«åãæ¿ããããã°ã€ã³ãã©ãŒã ãåé€ããŠãã£ããã衚瀺ããŸãã
MainContextã«ã¯ãããã«2ã€ã®ã³ã³ããã¹ããChatContextãšNavigationContextãå«ãŸããŠããŸãã ããã²ãŒã·ã§ã³ã³ã³ããã¹ãã¯ãMainContextã®åæåäžã«äœæãããŸãã çŸæç¹ã§ã¯ããŠãŒã¶ãŒãæ¿èªãããŠããããšãæ¢ã«ããã£ãŠãããããé£çµ¡å ãèªã¿èŸŒãããšãã§ããŸãã
ChatContextã®ãã¹ãŠã¯ããå°ãèå³æ·±ããã®ã§ãããŠãŒã¶ãŒãããã²ãŒã·ã§ã³ã¡ãã¥ãŒã§ãã£ãããéžæãããšããã®äœæïŒããã³ä»¥åã®ã³ã³ããã¹ãã®ãªãªãŒã¹ïŒãçºçããŸãã ChatContextèªäœã¯ãã¡ãã»ãŒãžã®è¿œå ãç·šéãåé€ãªã©ã®å€éšã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããŸãã ãã£ã¹ãã¬ã€ã¯ãããããã¡ãã»ãŒãžãæç»ãããåé€ããããšã§å¿çããŸãã ãã®å Žåãã³ã³ããã¹ãã¯éžæãããã£ããã®ã€ãã³ãã®ã¿ããµãã¹ã¯ã©ã€ãããå¿ èŠããããŸãã å¥ã®ãã£ããã®ã€ãã³ãã«ã¯èå³ããããŸããã ãã£ããã³ã³ããã¹ãã¯ãæ°ããã¡ãã»ãŒãžãªã©ã®ãŠãŒã¶ãŒã€ãã³ãã«ãå¿çããŸãã
ãã¹ããããã¢ãã«ã«ã¯éåžžã芪ã³ã³ããã¹ããžã®åç §ãå«ãŸããŠããŸããããå€éšã³ã³ããŒãã³ããšããåãããŠã€ãã³ããåä¿¡ããããåŒã³åºããè¡ã£ããã§ããŸãïŒäŸãšããŠãTDLibã®ã©ãããŒïŒã
éåææ§
ã»ãšãã©ã®GUIãã¬ãŒã ã¯ãŒã¯ãšåæ§ã«ãAvaloniaã§ã¯UIã¹ããªãŒã ã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹èŠçŽ ã®ã¿ã§ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã ãã®ã¹ã¬ããã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ãç¶æããããã«æå°éã®äœæ¥ãå®è¡ããããšãæãŸããã§ãã éåæ/åŸ æ©ã«ãããäœæ¥ãä»ã®ã¹ã¬ããã«å§ä»»ããããšãã¯ããã«ç°¡åã«ãªããŸããã RX.NETã¢ãããŒãã¯async / awaitãšéåžžã«äŒŒãŠããŸãããäžé£ã®ã€ãã³ããç°¡åã«æäœã§ããããã«ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¯Observableãåºç¯å²ã«äœ¿çšããŠéåææ§ãæäŸããŸãã äŸãèããŠã¿ãŸããã-ãŠãŒã¶ãŒã®é£çµ¡å ãèªã¿èŸŒã¿ãŸãã ã¢ããªã±ãŒã·ã§ã³ãããŠã³ããŒãããåŸããŠãŒã¶ãŒã«ã¯é£çµ¡å ã®ãªã¹ãã衚瀺ãããŸãã ç§ãã¡ã®å Žåãé£çµ¡å ã¯ãŠãŒã¶ãŒåãšåœŒã®åçã§ãã
ããŠã³ããŒãèªäœã¯ããããã¯ãŒã¯ãä»ããå žåçãªããŒã¿èŠæ±ã§ãã ãã®ãããªã¢ã¯ã·ã§ã³ã¯ãUIã¹ããªãŒã ã®å€ã§ç¢ºå®ã«å®è¡ããã®ãæé©ã§ãã ç°¡åãªè§£æ±ºçã¯async / awaitã䜿çšããããšã§ããã¡ã€ã³ã¹ã¬ãããããŠã³ããŒããéå§ããçµäºãããšéç¥ãåä¿¡ããŠââé£çµ¡å ã衚瀺ããŸãã ããŒãæã«ããé²è¡ç¶æ³ããŒã衚瀺ããŠãããã¯ã°ã©ãŠã³ãã§äœããã®äœæ¥ãè¡ãããŠããããšããŠãŒã¶ãŒã«ç¥ãããããšãã§ããŸãã
ãã®ã¢ãããŒãã«ã¯åé¡ããªãããã«æãããŸãã ãã ãã詳现ã«èª¿ã¹ããšãã¢ããªã±ãŒã·ã§ã³ãé£çµ¡å ãªã¹ãã®èŠæ±ãæºãããã®ã¯æéã®10ïŒ ïŒæŠç®ïŒã®ã¿ã§ãããæéã®æ®ãã®90ïŒ ã¯ç»åã®ããŠã³ããŒããšãã³ãŒãã§å ããããŠããããšãããããŸãã ãã®éããŠãŒã¶ãŒã¯åŸ æ©ããŠããŸããã ããè¯ãã¢ãããŒãã¯ãããŸããïŒ æåã®ãªã¯ãšã¹ããå®äºããçŽåŸã«é£çµ¡å ãªã¹ãã衚瀺ãããã§ã«ã第2ã®æ³¢ãã«ããç»åãããŠã³ããŒãããŠã¿ãŸãããïŒ
ååãšããŠããã®ã¿ã¹ã¯ã¯TPLã䜿çšããŠè§£æ±ºããããšãã§ããŸãããRx.NETã®äœ¿çšã¯ãã®ãããªã·ããªãªã®æ¹ãé©ããŠããŸãã èãæ¹ã¯éåžžã«åçŽã§ããããŒã¿ã®èªã¿èŸŒã¿ãå¥ã®ã¯ã©ã¹ã«å§ä»»ããŸãããä»åã¯Taskã§ã¯ãªãObservableãæåŸ ããŠããŸãã ããã«ããã1ã€ã§ã¯ãªãäžé£ã®ã€ãã³ãããµãã¹ã¯ã©ã€ãã§ããŸããæåã®ã€ãã³ãã¯ããŠã³ããŒããããé£çµ¡å ãªã¹ãã§ãããåŸç¶ã®ã€ãã³ãã«ã¯äœããã®æŽæ°ïŒããšãã°ãã¢ããããŒããããåçïŒãå«ãŸããŸãã
äŸã䜿çšããŠé£çµ¡å ãããŒãããããšãæ€èšããŠãã ããã ã³ã³ããã¹ãã¿ã¹ã¯ã«ã¯ãLoadContactsã®å®è¡çµæã®ãµãã¹ã¯ã©ã€ããå«ãŸããŸãã ObserveOnã¡ãœããã®åŒã³åºãã«æ³šæããŠãã ãã-ããã¯ãRx.NETãAvaloniaã¹ã±ãžã¥ãŒã©ã¹ã¬ããã§Subscribeã«æž¡ãããã³ãŒããå®è¡ããããã®åœä»€ã§ãã ãã®æ瀺ããªããšãContactsããããã£ãå€æŽããæš©å©ããããŸããã ã³ãŒãã¯UIã¹ã¬ãã以å€ã®ã¹ã¬ããã§å®è¡ãããŸãã
// NavContext.cs class NavContext : ReactiveObject { private ReactiveList<Contact> _contacts; public ReactiveList<Contact> Contacts { get => _contacts; set => this.RaiseAndSetIfChanged(ref _contacts, value); } public NavContext(ContactLoader contactLoader) { contactLoader.LoadContacts() .ObserveOn(AvaloniaScheduler.Instance) .Subscribe(x => { Contacts = new ReactiveList(x.Contacts); x.Updates .ObserveOn(AvaloniaScheduler.Instance) .Subscribe(u => { u.Contact.Avatar = u.Avatar; }); }); } }
ContactLoaderã¯ããããã¯ãŒã¯èŠæ±ã®å®è¡ãæ åœããŸãã ãªã¯ãšã¹ããå®äºãããšããµãã¹ã¯ã©ã€ããŒã«æŽæ°ãé ä¿¡ããå¥ã®ObservableãäœæãããŸãã ãã®çŽåŸã«ãåçãèªã¿èŸŒãŸããã®ãåŸ ããã«ãé£çµ¡å ã®ãªã¹ããé åžããæºåãæŽããŸãã æŽæ°ã¯ãããŠã³ããŒãæã«é ä¿¡ãããŸãã
// ContactLoader.cs class ContactLoader { IObservable<Load> LoadContacts() { return Observable.Create(async observer => { var contacts = await GetContactsAsync(); // networking var updates = Observable.Create(async o => { foreach (var contact in contacts) { // load avatar from remote server // ... var avatar = await GetAvatarAsync(); // networking o.OnNext(new Update(avatar)); } o.OnComplete(); }); observer.OnNext(new Load(contacts, updates)); observer.OnComplete(); }) } }
ã€ãã³ãã®ã·ãŒã±ã³ã¹ãå¶åŸ¡ã§ããŸãïŒçµåããã£ã«ã¿ãŒãå€æãªã©ã ããã¯ãã€ãã³ãã®ãœãŒã¹ãšã€ãã³ãèªäœãå€æ°ããå Žåã«éåžžã«äŸ¿å©ã§ãã Rx.NETã䜿çšãããšãObservableãå¹ççã«äœ¿çšã§ããŸãã
ç°¡åãªäŸïŒåçããã£ã¹ã¯ã«ãã£ãã·ã¥ãããšãããŠã³ããŒãã®é床ãå€§å¹ ã«åäžããŸããããã®ãããªå éã«ãããçæéã§å€§éã®æŽæ°ãçºçããã¹ã±ãžã¥ãŒã©ãŒã®äœæ¥ãè€éã«ãªããã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ã倱ãããå¯èœæ§ããããŸãã ãããåé¿ããããã«ããããã¡ãªã³ã°ã䜿çšããŸããäžåºŠã«100ããªç§ä»¥å ã«çºçãããã¹ãŠã®æŽæ°ãåŠçããåçãå«ãŸãªããšã³ããªãïŒäœããã®çç±ã§ïŒãã£ã«ã¿ãŒã§é€å€ããŸãã
x.Updates .Where(u => u.Avatar != null) .Buffer(TimeSpan.FromMilliseconds(100)) .ObserveOn(AvaloniaScheduler.Instance) .Subscribe(list => { foreach (var u in list) { u.Contact.Avatar = u.Avatar; } });
ãããã«
1ã€ã®èšäºã§ã䜿çšãããŠããåãã¯ãããžãŒã«ã€ããŠè©³ãã説æããããšã¯äžå¯èœã§ãã ç§ã¯æãèå³æ·±ããã®ãéžã³ãåçž®ããã圢ã§åºçºããããšããŸããã ãŸããã¢ããªã±ãŒã·ã§ã³èªäœã®å€ãã®ã³ã³ããŒãã³ãã¯åœ±é¿ãåããŸããã§ãããããã¹ãŠã®ã³ã³ããŒãã³ãã¯é¡äŒŒããŠãããåãååã«åºã¥ããŠããŸãã ãããªãç 究ã®ããã«ã次ã®ãªã³ã¯ã蚪ããããšããå§ãããŸãã