2020년은 오프라인 비지니스 환경에서 언텍트 비지니스 환경으로 변화하는 변곡점이라고 있을 같습니다. 그에 따라 이제는 PC 뿐만 아니라 다양한 모바일 디바이스에서 실행되는 크로스플랫폼 개발 환경이 더욱더 발전을 것이라고 생각됩니다.

 

2018 5 최초로 공개된 Uno Platform 크로스 플랫폼에서 실행되는 비지니스 응용 프로그램을 개발하는 가장  빠른 방법이라고 생각하며, 포스트에서 Microsoft Contoso UWP앱을 Uno Platform Prism으로 포팅할 참고할 사항이나 필요한 기술에 대해서 이야기를 하려고 합니다. Uno Platform 대한 자세한 사항은 여기 참고하시기 바랍니다.

 

Contoso UWP app

https://github.com/microsoft/Windows-appsample-customers-orders-database

UnoContoso app – Uno Platform

Uno.Samples/UI/UnoContoso at master · unoplatform/Uno.Samples (github.com)

 

포팅시 어려웠던 부분?

  1. Entity Framework Core 버전이 2.1에서 3.x 버전으로 변경되면서 발생한 문제를 해결하는데  시간이 오래 걸렸습니다. 변경 사항은 여기 참고하시기 바랍니다.
  2. Sqlite Entity Framework Core 이용해서 앱에서 직접 접근해서 사용하는 방식이 Wasm, iOS, macOS 등에서 원활하지 않아서, Web API 통해서만 사용할 있도록 수정하는데 시간이 걸렸습니다.
  3. Contoso UWP앱이 Event-driven 방식을 사용하고 있어서, 부분을 MVVM Pattern으로 변경하는 부분도 시간이 걸렸습니다.

프로젝트에 대한 간단한 설명

  • UnoContoso.Droid : 안드로이드 해더 프로젝트
  • UnoContoso.iOS : iOS 헤더 프로젝트
  • UnoContoso.macOS : macOS 헤더 프로젝트
  • UnoContoso.Uwp : Uwp 헤더 프로젝트
  • UnoContoso.Wasm : Wasm 헤더 프로젝트
  • UnoContoso.Models : 모델 프로젝트, .NET Standard 2.0
  • UnoContoso.Repository : 레파지토리 프로젝트, .NET Standard 2.0
  • UnoContoso.Service : 서비스 프로젝트, .NET Core 3.1
  • UnoContoso.Shared : 공유 프로젝트

Tips

  • NavigationView
    • AlwaysShowHeader=”False” :상단에 헤더를 표시하지 않습니다. 헤더를 표시하는 보다 표시 하지 않는 것이 아래의 이유로 인해서 개발이 용이 합니다.
      • iOS 경우 헤더의 위치가 다른 플랫폼과 다르게 위로 올라가서 표시됩니다.
      • Windows, Wasm, macOS에서는 헤더 위치에 CommandBar 표시하고, Android, iOS에서는 화면 하단에 표시하기 때문에, NavigationView.HeaderTemplate 사용이 어렵습니다.
    • NavigationViewBehavior : NavigationView 표시되는 메뉴를 동적으로 구현하고, 선택된 Menu ViewModel 바인딩하기 위해서 Behavior 만들었습니다. Behavior 일반적인 사항은 여기 참고하시기 바랍니다.
    • ContentControl : Prism에서 일반적으로 Region 지정하는 컨트롤입니다. 컨트롤을 통해서 View 네비게이션 됩니다. 자세한 사항은 Prism RegionNavigation 참고하시기 바랍니다.
      • 컨트롤의 Padding 화면의 기본 Margin입니다.
      • iOS 경우 ios:Padding=”10,20,0,0” 사용해야 합니다.
<!--Code1-->
        <NavigationView
            IsBackButtonVisible="Collapsed"
            OpenPaneLength="160"
            IsSettingsVisible="False"
            AlwaysShowHeader="False"
            IsTabStop="False">
            <i:Interaction.Behaviors>
                <behaviors:NavigationViewBehavior 
                    MenuItems="{Binding Menus}"
                    SelectedMenuItem="{Binding SelectedItem, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
            <ContentControl 
                prismRegions:RegionManager.RegionName="ContentRegion" 
				HorizontalContentAlignment="Stretch"
				VerticalContentAlignment="Stretch"
                not_ios:Padding="10,0,0,0"
                ios:Padding="10,20,0,0"/>
        </NavigationView>
  • x:Bind
    • Android iOS 앱의 성능 향상을 위해서 x:Bind 주로 사용했습니다.
    • x:Bind 사용하기 위해서 code behind에서ViewModel이라는 프로퍼티를 추가합니다. (Code2-1)
    • x:Bind 기본 mode OneTime입니다. 그래서, 프로퍼티의 데이터가 변경되는 곳이라면 mode=OneWay 반드시 추가해야 합니다.
    • 컨트롤의 이벤트와 뷰모델의 메소드를 x:Bind 직접 연결하는 방법은 사용할 없습니다.
    • IValueConverter 이용하는 경우 Android에서  x:Bind 사용할 없기 때문에, Binding 사용합니다. (Code2-2)
//Code2-1
public CustomerListViewModel ViewModel
{
    get { return DataContext as CustomerListViewModel; }
}
<!--Code2-2-->
                <TextBlock
                    Grid.Column="0"
                    Margin="0" Padding="0"
                    Text="{x:Bind Product.Name}" />
                <TextBlock
                    Grid.Column="2"
                    Margin="0" Padding="0"
                    HorizontalAlignment="Right"
                    Text="{Binding Product.ListPrice,
                        Converter={StaticResource StringFormatConverter},
                        ConverterParameter='{}{0:n}'}" />
  • Prism
    • View ViewModel 자동으로 연결해 줍니다. prismMvvm:ViewModelLocator.AutowireViewModel="True" 코드를 참고 합니다. 자세한 사항은 여기를 참고 합니다.(Code3-1)
    • RegionNavigation 사용하기 위해서는 App.xaml.cs → void RegisterTypes() 메소드에 RegisterForNavigation 이용해서 등록해야 합니다. (Code3-2)
    • DialogService 사용하는 화면은 View ViewModel 수동으로 연결 합니다. App.xaml.cs -} void RegisterTypes() 메소드에 있는 코드를 참고 합니다.   자세한 사항은 여기 참고 합니다. (Code3-3)
    • DelegateCommand ObservesProperty 이용하면, Command 사용여부를 쉽게 변경할 있습니다. 자세한 사항은 여기 참고 합니다. (Code3-4)
    • EventAggregator 이용하면 뷰모델과 뷰모델 사이에 커뮤니케이션을 있습니다. 이는 Loosely Coupled 연결입니다. 자세한 사항은 여기 참고 합니다. (Code3-5)
<!--Code3-1-->
<UserControl
    x:Class="UnoContoso.Views.OrderDetailView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnoContoso.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="using:Microsoft.Xaml.Interactivity" 
    xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
    xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:prismMvvm="using:Prism.Mvvm" 
    prismMvvm:ViewModelLocator.AutowireViewModel="True"
    xmlns:uc="using:UnoContoso.UserControls" 
    xmlns:stateTriggers="using:UnoContoso.StateTriggers" 
    xmlns:models="using:UnoContoso.Models" 
    x:Name="Root"
    mc:Ignorable="d">
//Code3-2
containerRegistry.RegisterForNavigation<CustomerListView>();
containerRegistry.RegisterForNavigation<CustomerDetailView>();
containerRegistry.RegisterForNavigation<HomeView>();
containerRegistry.RegisterForNavigation<OrderListView>();
containerRegistry.RegisterForNavigation<OrderDetailView>();
//Code3-3
containerRegistry.RegisterDialog<MessageControl, MessageViewModel>();
containerRegistry.RegisterDialog<ConfirmControl, ConfirmViewModel>();
//Code3-4
            ViewDetailCommand = new DelegateCommand(OnViewDetail,
                () => SelectedCustomer != null)
                .ObservesProperty(() => SelectedCustomer);
//Code3-5
Step 1. CustomerListViewModel.cs
            EventAggregator.GetEvent<CustomerEvent>()
                .Subscribe(ReceivedCustomerEvnet, false);

Step 2. CustomerDetailViewModel.cs
            EventAggregator.GetEvent<CustomerEvent>()
                .Publish(new EventArgs.CustomerEventArgs 
                { 
                    Changes = change,
                    Customer = Customer.Model
                });
                
Step 3. CustomerListViewModel.cs
        private void ReceivedCustomerEvnet(CustomerEventArgs obj)
        {
            switch (obj.Changes)
            {
                case Enums.EntityChanges.None:
                    break;
                case Enums.EntityChanges.Changed:
                    {
                        var customer = _allCustomers
                            .FirstOrDefault(c => c.Model.Id == obj.Customer.Id);
                        if (customer == null) return;
                        customer.Model = obj.Customer;
                        customer.UpdateProperty();
                    }
                    break;
                case Enums.EntityChanges.Added:
                    {
                        var customer = new CustomerWrapper(_contosoRepository, obj.Customer);
                        _allCustomers.Add(customer);
                    }
                    break;
                case Enums.EntityChanges.Deleted:
                    {
                        var customer = _allCustomers
                            .FirstOrDefault(c => c.Model.Id == obj.Customer.Id);
                        if (customer == null) return;
                        _allCustomers.Remove(customer);
                    }
                    break;
            }
        }
  • RelativePanel
    • 컨트롤을 관계에 의해 배치 합니다. 자세한 사항은 여기 참고 하시기 바랍니다.
    • VisualState 이용해서 상단에 위치한 CommandBar 위치를 하단으로 변경할 CommandBar 컨트롤에 RelativePanel.LeftOf RelativePanel.RightOf 입력되어있는 이름을 지워주어야 하단으로 이동이 가능합니다. 부분은 UWP에서의 동작과는 다르게 동작합니다.
<!--Code4-->
<VisualState>
  <VisualState.StateTriggers>
    <stateTriggers:MobileScreenTrigger />
  </VisualState.StateTriggers>
  <VisualState.Setters>
    <Setter Target="mainCommandBar.(RelativePanel.AlignBottomWithPanel)" Value="True" />
    <Setter Target="mainCommandBar.(RelativePanel.AlignLeftWithPanel)" Value="True" />
    <Setter Target="mainCommandBar.(RelativePanel.AlignRightWithPanel)" Value="True" />
    <Setter Target="mainCommandBar.(RelativePanel.LeftOf)" Value="" />
    <Setter Target="mainCommandBar.(RelativePanel.RightOf)" Value="" />
    <Setter Target="mainCommandBar.HorizontalAlignment" Value="Stretch" />
    <Setter Target="PageTitle.Margin" Value="30,4,0,0"/>
    <Setter Target="CustomerSearchBox.Width" Value="240" />
    <Setter Target="RootDataGrid.Margin" Value="0,10,0,40" />
    <Setter Target="CustomerListMobileView.Visibility" Value="Visible"/>
    <Setter Target="CustomerDataGrid.Visibility" Value="Collapsed"/>
  </VisualState.Setters>
</VisualState>
  • CommandBar
    • 커맨드 버튼을 배치하는 컨트롤 입니다. 기본적인 사항은 여기 참고하시기 바랍니다.
    • CommandBarBehavior 크기가 변하면 DefaultLabelPosition Right에서 Bottom으로 이동 시키기 위해서 추가한 Behavior입니다.
    • DefaultLabelPosition 프로퍼티가 Uno에서 미구현 프로퍼티이기 때문에, 대부분의 플랫폼에서는 기본값 Bottm 가지고 있습니다.
<!--Code5-->
            <CommandBar 
                x:Name="mainCommandBar"
                Background="White"
                HorizontalAlignment="Right"
                DefaultLabelPosition="Right"
                RelativePanel.LeftOf="CustomerSearchBox"
                RelativePanel.RightOf="PageTitle">
                <i:Interaction.Behaviors>
                    <behaviors:CommandBarBehavior/>
                </i:Interaction.Behaviors>
                <AppBarButton
                    Icon="Contact"
                    Label="View details"
                    ToolTipService.ToolTip="View details" 
                    Command="{x:Bind ViewModel.ViewDetailCommand}"/>
                <!--skip lines-->
                <AppBarButton
                    Icon="Refresh"
                    Label="Sync"
                    ToolTipService.ToolTip="Sync with server" 
                    Command="{x:Bind ViewModel.SyncCommand}"/>
            </CommandBar>
  • CollapsibleSearchBox
    • UserControl 이용해서 만든 검색용 컨트롤입니다.
    • Uno에서 그래픽 아이콘은 SymbolIcon 컨트롤을 이용해야, 플랫폼에서도 정상적으로 아이콘이 출력됩니다.
<!--Code6-->
        <ToggleButton
            x:Name="searchButton"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Background="Transparent"
            Checked="SearchButton_Checked"
            Visibility="Collapsed"
            Padding="4">
            <SymbolIcon Symbol="Find" />
        </ToggleButton>
  • ListView
    • 모바일 디바이스에서는 화면에 출력되는 항목의 갯수와 가로 스크롤바의 유무에 따라서 세로 스크롤 성능에 영향을 미치기 때문에 DataGrid보다는 ListView 이용하는 것이 좋습니다. 자세한 사항은 여기 참고 합니다.
    • macOS에서는 아직 DataGrid 사용할 없기 때문에 ListView 사용합니다. 하지만, macOS ListView 컨트롤 내부에 ScrollView 없기 때문에 세로 스크롤이 불가능한 것으로 보입니다. macOS 지원은 점점 추가될 것으로 생각합니다.
  • DataGrid
    • Data Grid 형태로 보여주며, 수정도 가능한 컨트롤이며, Windows Community Toolkit 설치해야 사용할 있습니다. 자세한 사항은 여기 참고 합니다.
    • DataGridBehavior Sort기능과 마우스 오른쪽 버튼을 지원하기 위해서 만들었습니다.
    • 컬럼에 프로퍼티를 바인딩 할때 x:Bind 사용할 없습니다.
<!--Code7-->
<toolkit:DataGrid
    x:Name="OrderListDataGrid" BorderThickness="0" 
    CanUserReorderColumns="False" CanUserResizeColumns="False"
    GridLinesVisibility="None" IsReadOnly="True"
    AutoGenerateColumns="False" Margin="0,10,0,0"
    ItemsSource="{x:Bind ViewModel.Orders, Mode=OneWay}"
    SelectedItem="{x:Bind ViewModel.SelectedOrder, Mode=TwoWay}"
    ContextFlyout="{StaticResource DataGridContextMenu}">
	<i:Interaction.Behaviors>
	  <behaviors:DataGridBehavior/>
	</i:Interaction.Behaviors>
	<toolkit:DataGrid.Columns>
	  <toolkit:DataGridTextColumn
	    Header="Invoice" Tag="InvoiceNumber" Binding="{Binding InvoiceNumber}"/>
	  <toolkit:DataGridTextColumn
	    Header="Customer" Tag="CustomerName" Binding="{Binding CustomerName}"/>
	  <toolkit:DataGridTemplateColumn
	    Header="Date" Tag="DatePlaced">
	    <toolkit:DataGridTemplateColumn.CellTemplate>
	      <DataTemplate>
	        <TextBlock
	          VerticalAlignment="Center" Margin="12,0"
		   Text="{Binding DatePlaced, Mode=OneWay,
                     Converter={StaticResource StringFormatConverter},
                     ConverterParameter='{}{0:d}'}" />
	      </DataTemplate>
	    </toolkit:DataGridTemplateColumn.CellTemplate>
	  </toolkit:DataGridTemplateColumn>
         <!-- Skip lines -->
	  <toolkit:DataGridTextColumn
	    Header="Status" Binding="{Binding Status}"/>
	</toolkit:DataGrid.Columns>
</toolkit:DataGrid>
  • VisualState
    • 특정 상태일 UI 요소의 시각적 모양을 지정할 있는 기능입니다. 자세한 사항은 여기 참고 합니다.
    • AdaptiveTrigger : 윈도우 속성을 기반으로 시각적 상태를 선언하는 트리거 입니다. 자세한 사항은 여기 참고 합니다.  
    • VisualState 이용해서 디자인 작업을 할 , 기본 크기에 대한 디자인은 화면에 왼쪽 상단에서8” Tablet(1280x800) 선택하고, 최소 크기에 대한 디자인은 6”Phone(1920x1080) 선택해서 작업하면 약간 편하게 작업할 있습니다.
    • 최소 크기인 경우 PageTitle 컨트롤의 왼쪽에 30 Margin 추가해서 햄버거 버튼과 겹치는 현상을 방지 합니다.
    • MobileScreenTrigger 윈도우 크기가 변경될 실행 중인 디바이스의 이름을 가지고 오고, Mobile이라는 이름을 포함하면 SetActive() 이용해서 VisualState 변경합니다. UIViewSettings.GetForCurrentView().UserInteractionMode Uno에서  미구현 상태라 주석 처리를 했습니다.
<!--Code8-->
<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState>
      <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowWidth="{StaticResource LargeWindowSnapPoint}" />
      </VisualState.StateTriggers>
    </VisualState>
  <VisualState>
    <VisualState.StateTriggers>
      <AdaptiveTrigger MinWindowWidth="{StaticResource MediumWindowSnapPoint}" />
    </VisualState.StateTriggers>
  </VisualState>
  <VisualState>
    <VisualState.StateTriggers>
      <AdaptiveTrigger MinWindowWidth="{StaticResource MinWindowSnapPoint}" />
    </VisualState.StateTriggers>
    <VisualState.Setters>
      <Setter Target="PageTitle.Margin" Value="30,4,0,0"/>
    </VisualState.Setters>
  </VisualState>
  <VisualState>
    <VisualState.StateTriggers>
      <stateTriggers:MobileScreenTrigger />
    </VisualState.StateTriggers>
    <VisualState.Setters>
    <!-- Skip lines -->
    </VisualState.Setters>
  </VisualState>
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>
  • BackButton
    • 뒤로가기 버튼입니다. GoBackCommand 커맨드는 ViewModelBase 선언되어 있습니다.
<!--Code9-->
            <Button 
                x:Name="BackButton"
                Style="{StaticResource NavigationBackButtonNormalStyle}"
                Command="{x:Bind ViewModel.GoBackCommand}"/>
  • TextBox
    • 일반 텍스트를 표시하고 편집하는 사용하는 컨트롤 입니다. 자세한 사항은 여기 참고 합니다.
    • Text 프로퍼티에 TwoWay바인딩을 때는 UpdateSourceTrigger=PropertyChanged 이용하는 것이 좋습니다. 왜냐하면, 내용을 수정하면 바로 바인딩된 프로퍼티가 수정되기 때문입니다. 기본값은 LostFocus입니다. 
<!--Code10-->
<TextBox
    x:Name="FirstName"
    MinWidth="120"
    Margin="0,8,16,8"
    Header="First name"
    IsReadOnly="{x:Bind ViewModel.Customer.IsInEdit, 
	    Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
    RelativePanel.AlignLeftWithPanel="True"
    Text="{x:Bind ViewModel.Customer.FirstName, Mode=TwoWay, 
	    UpdateSourceTrigger=PropertyChanged}" />
  • InvoiceTemplate (DataTemplate)
    • 데이터 개체의 시각적 구조를 만드는데 사용합니다. 자세한 사항은 여기 참고 합니다.
    • HyperlinkButton 1개가 존재하며 Command win not_win으로 나누어져 있습니다. 각 플랫폼별 xaml 코드를 적용하는 방법은 여기를 참고 합니다.
    • Windows에서는 win:Command="{Binding Source={StaticResource ViewModelElement}, Path=ViewModel.ViewInvoiceCommand}" 사용해야 Command 실행됩니다.
    • Windows 아닌 경우에는 not_win:Command="{Binding ElementName=DataGrid,                     Path=DataContext.ViewInvoiceCommand}" 사용해야 Command 실행됩니다.
    • Windows에서 ElementName=DataGrid 이용하는 방법이 않되는 이유는 모릅니다.
<!--Code11-->
<DataTemplate x:Key="InvoiceTemplate">
    <HyperlinkButton
        Content="{Binding InvoiceNumber}"
        Margin="12,0"
        win:Command="{Binding Source={StaticResource ViewModelElement}, 
            Path=ViewModel.ViewInvoiceCommand}"
        not_win:Command="{Binding ElementName=DataGrid, 
            Path=DataContext.ViewInvoiceCommand}"
        CommandParameter="{Binding}"/>
</DataTemplate>
  • Etc
    • 만약 솔루션에 .Net Standard 프로젝트를 포함하고, 사용한다면, Wasm 프로젝트의 LinkerConfig.xml 파일에 해당 내용을 추가해야 합니다.
<!—LinkerConfig.xml -->
<linker>
  <assembly fullname="UnoContoso.Wasm" />
  <assembly fullname="Uno.UI" />
  <assembly fullname="System.Core">
	<!-- This is required by JSon.NET and any expression.Compile caller -->
	<type fullname="System.Linq.Expressions*" />
  </assembly>
  <assembly fullname="UnoContoso.Models"/>
  <assembly fullname="UnoContoso.Repository"/>
</linker>

이상으로 작업을 하면서 알게된 몇가지 팁들을 정리했습니다. 앞으로도 좋은 정보가 있으면 꾸준히 올리도록 하겠습니다.

Facebook : https://www.facebook.com/kaki104

Twitter : https://twitter.com/kaki104

Youtube : http://youtube.com/FutureOfDotNet

 

블로그 이미지

kaki104

This blog covers the latest technologies in Microsoft .Net. In 2020, I will be talking about Uno Platform frequently. http://youtube.com/FutureOfDotNet https://twitter.com/kaki104

댓글을 달아 주세요


기본 사용방법 설명

Constructor Injection – 생성자 주입

- Resolve시에 기본으로 사용하는 방식
- private readonly T _instance; 를 이용해서 내부에서 사용
- Multiple Parameters
  public Driver(ICar car, ICarKey key)
  private readonly ICar _car;
- Multiple Constructors
  [InjectionConstructor] public Driver(ICar car)
  public Driver(string name)
- Primitive Type Parameter
  public Driver(ICar car, string driverName)

 

https://youtu.be/UHrrIDBubdg

 

UnityContainer Detail & Examples - Prism으로 시작하는 UWP app part15 - 2

 

Property Injection

- Attribute를 이용해서 Injection
- public T Instance { get; set;} 을 이용
- Dependency Attribute
  [Dependency] public ICar Car { get; set; }
- Named Mapping
  [Dependency("MyCar")] protected ICar Car { get; set; }
- Run-time Configuration
  public ICar MyCar { get; set; }
  unityContainer.RegisterType<IDriver, UWPDriverRuntime>(new InjectionProperty("MyCar", new BMW()));


Method Injection

- Attribute를 이용해서 Injection
- private readonly T _instance; 를 이용해서 내부에서 사용
- 생성자를 이용할 수 없는 경우 사용
- InjectionMethod Attribute
  [InjectionMethod] public void UseCar(ICar car) { _car = car; }
- Run-time Configuration
  public void MyCar(ICar car) { _car = car; }
  unityContainer.RegisterType<IDriver, UWPDriverRuntimeMethod>(new InjectionMethod("MyCar", new Audi()));


Overrides

- 등록된 Type이외의 Type을 Injection 시키는 방법
- ResolverOverride를 이용해서 등록된 Type을 재정의 할 수 있음
- ParameterOverride
  unityContainer.Resolve(
  new ParameterOverride("car", new BMW()));
  Override Multiple Parameters
  new ParameterOverrides {  { "car1", new Audi() },
                         { "carKey1", new AudiKey() }, 
                         { "car2", new BMW() },                 
                         { "carKey2", new BMWKey() }}
- PropertyOverride
  unityContainer.Resolve(new PropertyOverride("Car", new BMW()));
- DependencyOverride
  unityContainer.Resolve(new DependencyOverride(typeof(ICar), new BMW()));


Lifetime Manager

- UnityContainer에 등록된 객체에 대한 수명을 관리하는 방법을 지정할 수 있음
1. TransientLifetimeManager
   기본 수명 관리 방법, Resolve호출시 새로운 객체를 생성해서 반환
2. ContainerControlledLifetimeManager
   처음 Resolve시 싱글톤 객체를 생성하고, 이후 Resolve할 때마다 반환 
3. HierarchicalLifetimeManager
   2 항목과 동일, 추가로 하위 컨테이너가 자체 단일 객체를 만들어 반환 – 상위 컨테이너와 하위 컨테이너가 서로 다른 객체 관리
4. PerResolveLifetimeManager
   1 항목과 동일, 재귀호출시 생성된 객체는 재사용함
5. PerThreadLifetimeManager
   스래드당 단일 객체를 생성
6. ExternallyControlledLifetimeManager
   생성된 객체에 대한 약한 참조만 유지. 사용자 정의 수명관리자를 만들어서 사용할 수 있음

 

https://youtu.be/fQunFpAvTsg

소스

https://github.com/kaki104/PrismSample2019

블로그 이미지

kaki104

This blog covers the latest technologies in Microsoft .Net. In 2020, I will be talking about Uno Platform frequently. http://youtube.com/FutureOfDotNet https://twitter.com/kaki104

댓글을 달아 주세요

1. IoC, DIP, DI, IoC Container

- IoC(Inversion of Control)
    클래스간의 느슨한 결합(loose coupling)을 만들기 위해 OOP에서 제어를 뒤집을 것을 권장하는 디자인 원칙(principle)
- DIP(Dependency Inversion Principle)
    클래스간의 느슨한 결합(loose coupling)을 만들기 위한 원칙(principle) 중 하나
    고수준 모듈(High-level)이 저수준 모듈(Low-level)에 의존해서는 안된다는 원칙. 둘다 추상화(예: interface)에 의존해야 함
- DI(Dependency Injection)
    IoC 원칙을 구현하는 디자인 패턴
    종속 객체를 주입
- IoC Container
    어플리케이션 전체에서 자동 종속성 주입을 관리하는 프레임워크
    Unity, Ninject, StructureMap, Autofac 등
- 위의 내용들을 관통하는 핵심
    가능한 모든 클래스는 Interface를 이용해서 추상화하고 Container를 이용해서 Injection 해서 사용한다.

2. Prism Framework features

- EventAggregator
    응용 프로그램에서 느슨하게 결합된 (loosely coupled) 구성 요소 간의 통신을 가능하게하는 이벤트 메커니즘(PubSubEvent)을 제공  
- UnityContainer
    가볍고 확장 가능한 종속성 주입 컨테이너 (Dependency Injection Container) 
- Region
    런타임에 느슨하게 결합된 (loosely coupled) UI로 구성된 레이아웃을 만들기 위한 방법
- Modules
    관련된 기능이나 UI를 내포한 클래스 라이브러리들을 느슨하게 결합 (loosely coupled) 하기 위한 방법
- UWP에서 사용가능한 버전
    Prism.Unity 6.3, Prism.Core 6.3
    UWP에서는 Region 기능 사용 못함


3. UnityContainer Overview

- 가볍고 확장 가능한 종속성 주입(Dependency Injection) 컨테이너 
- 특징
Interface Type이나 기본 Type에 대한 단순 맵핑 등록
기존 인스턴스 등록 지원
디자인 타임 등록은 물론 코드 등록 지원
생성자, 속성 또는 메서드를 통해 등록된 Type을 자동으로 주입
지연(deferred) 솔루션 지원
중첩 컨테이너 지원
수명 관리자를 이용해서 인스턴스를 자동으로 disposing
서비스 위치 기능 지원
Type 차단 및 인스턴스 차단을 지원


4. UnityContainer 사용하기(RegisterType)

UnityContainer.RegisterType Method
Type 맵핑을 위한 메소드
대표적인 Type등록 방법 및 예제
unityContainer.RegisterType();
unityContainer.RegisterType(); //생략가능
unityContainer.RegisterType<Interface, T>();
unityContainer.RegisterType<IAddPerson, AddPersonControl>();
unityContainer.RegisterType<Interface, T>(string);
unityContainer.RegisterType<IAddPerson, AddPersonControl>(“Control”);
unityContainer.RegisterType<IAddPerson, AddPersonPage>(“Page”);


5. UnityContainer 사용하기(Resolve)

UnityContainer.Resolve Method
컨테이너로부터 Type을 인스턴스 시켜주는 메소드
대표적인 Resolve 방법 및 예제
var t = unityContainer.Resolve();
var t = unityContainer.Resolve();
var t = unityContainer.Resolve();
var t = unityContainer.Resolve();
var t = unityContainer.Resolve(string);
var t = unityContainer.Resolve(“Page”);

https://youtu.be/8L9lBghcFbc

 

Prism으로 시작하는 UWP app 개발 Part1-14.pdf
1.89MB

블로그 이미지

kaki104

This blog covers the latest technologies in Microsoft .Net. In 2020, I will be talking about Uno Platform frequently. http://youtube.com/FutureOfDotNet https://twitter.com/kaki104

댓글을 달아 주세요

WebView - Async, EventAggregator - Prism으로 시작하는 UWP app Part11

 

JavaScript에서 Async 메소드를 호출하고 결과를 처리하는 방법
Windows Runtime Component에서 비동기 메소드를 처리하는 방법
IEventAggregator를 이용해서 UWP나 다른 프로젝트로 이벤트를 넘기는 방법 등에 대해서 다루고 있습니다.

 

* Async : Windows Runtime Component에서 async Task 메소드 사용 방법
* IEventAggregator : 개념 및 사용 방법

 

https://youtu.be/LBS-UJtG2PQ

소스

https://github.com/kaki104/PrismSample2019

블로그 이미지

kaki104

This blog covers the latest technologies in Microsoft .Net. In 2020, I will be talking about Uno Platform frequently. http://youtube.com/FutureOfDotNet https://twitter.com/kaki104

댓글을 달아 주세요

* Prism 앱의 레이어에 대해 설명합니다.


. 재정의 불가능 영역 : Popup, ContentDialog, MediaElement
. 재정의 가능 영역 : 일반 Page
. 기타 영역 : MessageDialog

 

 

 

* 소스 : https://github.com/kaki104/PrismSample

블로그 이미지

kaki104

This blog covers the latest technologies in Microsoft .Net. In 2020, I will be talking about Uno Platform frequently. http://youtube.com/FutureOfDotNet https://twitter.com/kaki104

댓글을 달아 주세요