2016년 4월 25일 월요일

Visual Studio emulator for Android 사용 시 adb reverse 안되는 현상

Windows에서 Visual Studio emulator for Android를 사용하던 중
adb reverse 가 안되는 현상이 있어서 찾아보니
원인은 emulator의 Android 버전이었음.

adb reverse가 Android 5.0(API21) 이상에서 부터 사용되는 기능이므로
emulator Android 버전이 그 미만이면 사용 불가능함.

[증상]
D:\>adb reverse tcp:8081 tcp:8081
error: closed

[참고]
http://facebook.github.io/react-native/docs/running-on-device-android.html#using-adb-reverse

* Emulator에서 Reload JS를 하기 위해서 Developer menu를 여는 방법은 다음과 같다.
 : adb shell input keyevent 82

2016년 4월 20일 수요일

Xamarin.Forms Guide, Webinar 대충 정리

죄송하게도 본 게시물은
아래 Xamarin 가이드를 보고 개인적으로 필요한 부분만을 정리한 것이므로
해당 링크를 직접 보시는 것이 좋습니다.
https://docs.xamarin.com/guides/xamarin-forms/


[Xamarin.Forms]

 : Cross-platform UI tookit으로 Android, iOS, Windows Phone에서 사용 할 수 있는 Native UI를 쉽게 만들 수 있게 해준다.
 : Xamarin.Forms을 사용하여 작성된 app은 결과적으로 Native application이므로 hybrid app과 같이 browser sand-boxing, limited APIs, performance 이슈가 없고 Platform에서 제공하는 feature들(CoreMotion/PassKit/StoreKit on iOS, NFC/Google Play Service on Android, Tiles on Windows)을 사용할 수 있음.
 : UI를 구현함에 있어 C#으로 모든 부분을 구현할 수 있고 XAML(Extensible Application Markup Language)을 사용하여 UI를 구성할 수도 있다.

[Xamarin.Forms Guide]

 : https://docs.xamarin.com/guides/xamarin-forms/

PDF Book Download
 : https://docs.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/

Xamarin에서 UI를 제공하는 방법에는 Xamarin.Forms을 사용하여 UI 관련 코드를 재사용하거나 Xamarin.iOS, Xamarin.Andoid를 사용하여 직접 Platform-specific API를 사용하는 두가지 방법이 있음.

Xamarin.Forms 사용이 적절한 App 종류는
 - Data entry apps
 - Prototypes and proofs-of-concept
 - Apps that require little platform-specific functionality
 - Apps where code sharing is more important than custom UI


Xamarin.iOS, Xamarin.Android 사용이 적절한 App 종류는
 - Apps that require specialized interactions
 - Apps with highly polished design
 - Apps that use many platform-specific APIs
 - Apps where custom UI is more important than code sharing


즉 GUI적으로 platform specific한 부분이 사용되거나
GUI적으로 좀 더 뭔가 advance한 처리가 필요한 경우에는 Xamarin.Forms가 부적절하겠음.


[Requirements]
: https://developer.xamarin.com/guides/xamarin-forms/getting-started/installation/

amarin.Forms applications can be written for the following operating systems:
  • Android 4.0.3 (API 15) or higher #
  • iOS 6.1 or higher
  • Windows Phone 8.1 (WinRT, using Visual Studio) #
  • Windows 8.1 Tablet/Desktop Apps (WinRT, using Visual Studio) #
  • Windows 10 Universal Apps (Phone/Tablet/Desktop, using Visual Studio)#
  • Windows Phone 8 Silverlight (using Visual Studio) DEPRECATED #

: iOS, OS X용을 개발하려면 Xcode 7이 필요하구나...

Any Xamarin Studio version from 5.0 can be used to develop Xamarin.Forms applications on OS X Yosemite (10.10) or newer. To develop iOS applications, Xcode 7 is also required.


[An Introduction to Xamarin.Forms]

: https://developer.xamarin.com/guides/xamarin-forms/getting-started/introduction-to-xamarin-forms/

UI를 구성하는데 있어 두가지의 방법이 있음.
 - C# 코드로 모두 구현하는 방법
 - XAML(Extensible Application Markup Language)을 사용하여 구성하는 방법

"Hello, Forms !"
public class App : Application
{
  public App ()
  {
    MainPage = new ContentPage {
      Content =  new Label
      {
        Text = "Hello, Forms !",
        VerticalOptions = LayoutOptions.CenterAndExpand,
        HorizontalOptions = LayoutOptions.CenterAndExpand,
      }
    };
  }
}

[View and Layouts]

1. Pages
 : cross-platform mobile application screens
 : Xamarin.Forms Pages


2. Layouts
 : View를 담은 container의 역할
 :  Xamarin.Forms Layouts



3. Views
 : UI controls (ex labels, buttons, text entry boxes, etc.)
 : ActivityIndicator, BoxView, Button, DatePicker, Editor, Entry, Image, Label, ListView, OpenGLView, Picker, ProgressBar, SearchBar, Slider, Stepper, Switch, TableView, TimePicker, WebView
 :  Xamarin.Forms Views

4. Cells
 : list의 item 표시에 특화되어 각 item을 표시할 때 사용 됨.
 : EntryCell, SwitchCell, Text Cell, ImageCell
 : Xamarin.Forms Cells


[Model-View-ViewModel (MVVM)]

 : http://hackersstudy.tistory.com/71
 : http://secretroute.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4MVC-MVP-and-MVVM
 : 기존 MVC의 문제와 MVP의 문제를 해결하고자 나온 Architectural model 이며 View Model와 View간의 dependency를 줄이고자 나온 것이며 Command와 Data binding을 사용하여 해결한다고 함.

[Data Binding]

Data binding은 source와 target를 연결한다. source는 data를 제공하고 target은 source에서 제공한 data를 사용한다.


binding의 이점은 data와 view간의 동기화를 걱정할 필요가 없다는 점이고 data 변경 시 source object는 자동으로 binding framework에 등록된 target object로 변경사항을 보내게 된다.

View의 control(target)과 ViewModel의 model(source)을 binding을 위해 다음 두 절차가 필요하다. (하단 샘플 참고)
- View의 BindingContext property로 source(ViewModel의 model)이 지정 되어야 한다.
- View의 control과 ViewModel의 model간의 binding은 XAML의 Binding markup extension이나 C#의 SetBinding() 방법을 사용해야 한다.

[Xamarin.Forms Webinar]

 : Xamarin.Forms 관련 개념 설명, 기본 Layout, View 예제 code, MVVM 관련 예제 code와 설명이 괜찮다.
 : https://fast.wistia.net/embed/iframe/w2p6ayviev?popover=true
 : http://www.slideshare.net/Xamarin/introduction-to-xamarinforms


[Page, Layout, Controls Demo 예제인 ListPage 코드]
 : Demo에서는 TabbedPage(TimeListPage)를 사용하여 두개의 ContentPage를 사용하는 예제임.
 : ContentPage 중 하나인 ListPage에서는 StackLayout를 사용하여 Button Control과 버튼 클릭 시간을 보여주는 ListView를 보여주며 Page, Layout, Control들의 간단한 사용, 추가 방법에 대해서 알려줌.

using Xamarin.Forms;

namespace App1
{
    public class ListPage : ContentPage
    {
        ObservableCollection<string> Items;
        public ListPage()
        {
            Title = "List Page";
            Items = new ObservableCollection<string>();
            var list = new ListView();

            list.ItemsSource = Items;
            list.ItemSelected += (sender, args) =>
            {
                if (list.SelectedItem == null)
                    return;

                this.Navigation.PushAsync(new ContentPage
                {
                    Title = "page 2",
                    Content = new Label
                    {
                        Text = args.SelectedItem as string
                    }
                });
                list.SelectedItem = null;
            };

            var button = new Button
            {
                Text = "Add Time"
            };

            button.Clicked += (sender, args) =>
            {
                Items.Add(DateTime.Now.ToString("F"));
            };

            var stack = new StackLayout
            {
                Orientation = StackOrientation.Vertical,
                Spacing = 10,
                Children = { list, button }
            };

            Content = stack;
        }
    }

    public class TimeListPage : TabbedPage
    {
        public TimeListPage()
        {
            this.Title = "Time List";
            Children.Add(new ListPage());
            Children.Add(new ContentPage
            {
                Title = "Tab2",
                Padding = 10,
                Content = new Label
                {
                    Text = "Hello from Tab 2"
                }
            });
        }
    }
}

[MVVM, Binding 예제인 LoginPage 관련]





: username, display 변경 관련
 . View(LoginPage)의 entry가 UsernameViewModel의 Username과 Binding 되었음.
 . ViewModel(UsernameViewModel)에서 INotifyPropertyChanged의 PropertyChanged()를 호출하여 username과 Display가 변경되었음을 알릴 수 있음.
 . View(LoginPage)의 label이 UsernameViewModel의 Display와 Binding 되어 있기 때문에 label의 text property가 업데이트 되게 됨.


Command, Action
 : Command에는 실행할 Action과 실행 가능여부를 확인하는 Action이 정의 됨.

namespace Xamarin.Forms
{
    //     Defines an System.Windows.Input.ICommand implementation wrapping a generic Action<T>.
    //
    //     The following example creates a new Command and set it to a button.
    public sealed class Command<T> : Command
    {
        public Command(Action<T> execute);
        public Command(Action<T> execute, Func<T, bool> canExecute);
    }
}

namespace System
{
    public delegate void Action<in T>(T obj);
}

 : button 클릭 시
  . loginCommand은 실행할 ExeuteLoginCommand Action과 실행 여부를 확인하는 CanLogin Action을 가지는 Command로 초기화 됨.
  . View(LoginPage)의 button은 UsernameViewModel의 LoginCommand와 binding되어 있어 button 클릭 시 LoginCommand에 Username 값을 parameter로 넘겨 실행한다.
 . ViewModel(UsernameViewModel)의 CanLogin에서 username을 확인한 뒤 ExecuteLoginCommand가 호출되어 TimeListPage로 이동하게 된다.


using Xamarin.Forms;

namespace App1
{
    public class UsernameViewModel : INotifyPropertyChanged
    {
        private INavigation navigation;
        public UsernameViewModel(INavigation navigation)
        {
            this.navigation = navigation;
        }
        private string username = string.Empty;
        public string Username
        {
            get { return username; }
            set
            {
                if (username == value)
                    return;

                username = value;
                OnPropertyChanged("Username");
                OnPropertyChanged("Display");
            }
        }

        private Command<string> loginCommand;
        public Command LoginCommand
        {
            get { return loginCommand ?? (loginCommand = new Command<string>(ExecuteLoginCommand, CanLogin)); }
        }

        private bool CanLogin(string name)
        {
            return !string.IsNullOrWhiteSpace(name);
        }

        private void ExecuteLoginCommand(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
                return;
            navigation.PushAsync(new TimeListPage());
        }

        public string Display
        {
            get { return "Hello there: " + username; }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string name)
        {
            if (PropertyChanged == null)
                return;

            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public class LoginPage : ContentPage
    {

        public LoginPage()
        {
            this.BindingContext = new UsernameViewModel(Navigation);

            var entry = new Entry
            {
                Placeholder = "Enter Username"
            };

            entry.SetBinding<UsernameViewModel>(Entry.TextProperty,
                vm => vm.Username, BindingMode.TwoWay);

            var label = new Label
            {

            };

            label.SetBinding<UsernameViewModel>(Label.TextProperty,
                vm => vm.Display);

            var button = new Button
            {
                Text = "Login"
            };

            button.SetBinding<UsernameViewModel>(Button.CommandProperty,
               vm => vm.LoginCommand);
            button.SetBinding<UsernameViewModel>(Button.CommandParameterProperty,
               vm => vm.Username);

            Content = new StackLayout
            {
                Padding = 10,
                Spacing = 10,
                Children = { entry, label, button }
            };

        }
    }
}

XAML도 봐야 하는데...

2016년 4월 18일 월요일

Build a Cross Platform Application with Xamarin

죄송하게도 본 게시물은
아래 Xamarin 가이드를 보고 개인적으로 필요한 부분만을 정리한 것이므로
해당 링크를 직접 보시는 것이 좋습니다.

https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/


[Shared Projects vs Portable Class Libraries]

 : https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/sharing_code_options/

갑자기 좀 처음에 이게 나와서 좀 생뚱맞긴 하지만 Xamarin 개발 시 아래 두 방법 중 하나를 선택하는 것이 필수 이므로 설명하고 들어가는게 아닌가 함.

[Shared Projects]
 : Source code 수준(#if compiler를 사용)에서 platform-specific requirement를 처리하는 shared project를 만들어 Cross platform app 개발 방법
 : 장점은 잘 모르겠고 #if의 폐혜가 그대로 나오지 않을까 생각함.
 : 좀 더 찾아보니 Portable class libraries 방법에 비해 .NET framework feature를 모두 사용할 수 있다고 함.







[Portable Class Libraries]
 : Platform specific 기능을 사용할 수 있도록 Interface를 제공하는 PCL(Portable Class Library)를 만들어 사용하는 Cross platform app 개발 방법

 : 공통의 기능을 별도의 DLL로 분리해서 업데이트 함에 있어 코드의 분리, 유지보수의 편의성, 일관적인 공통 기능 제공 등에서의 장점을 가지겠지만 공통의 기능이 최소화 되어 도출 될 수 밖에 없고 platform specific한 부분이 각 app에서 따로 구현이 되어야 하는 점이 있음.



좀 더 찾아보니 장단점이 다양해서 각자 판단하시길.
사실 어찌 보면 다양함을 지원함과 공통의 부분을 최대화 하는 것은 상반되는지라 적당한 수준을 찾는게 맞을듯?

http://www.slideshare.net/gilbok/xamarinforms-mvp-comcamp-2015?qid=490ed12a-a153-4a9c-aa83-8d35eb19e105&v=&b=&from_search=1
 : PCL과 Shared Project의 장단점을 잘 소개 하고 있는 PT. 내용 괜찮음.

http://stackoverflow.com/questions/30634753/what-is-the-difference-between-a-shared-project-and-a-class-library-in-visual-st
http://hotkrossbits.com/2015/05/03/xamarin-forms-pcl-vs-shared-project/

[Overview]

https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_0_-_overview/

 : 일반 적인 Cross Platform은 "write-once, run everywhere" 즉, Common set을 정의하여 여러 플랫폼을 대응하는 방법을 취해 비용 최소화의 장점을 가지나 common set이 각 platform의 최소 기능으로 이뤄지는 점 GUI가 general 하게 구성된다는 단점이 있음.
그에 반해 Xamarin에서는 Naitve UI을 구현/제공할 수 있는 방법 제공과 UI를 제외한 data storage, business logic 등을 재사용할 수 있음 점을 장점으로 내세우고 있는 듯하다.



Xamarin Cross-Platform App을 만들 때 필요한 주요 Feature들은 다음과 같음.

 - C# 사용
  : C#으로 코드를 작성하고 iOS, Android, Windows Phone 대상 app으로 변환 가능
 - MVC design pattern
  : Core, User-Interface을 분리하여 app 개발을 할수 있다. MVC(Model-View-Controller), MVVM(Model-View-ViewModel) design approach를 사용할 수 있음.
 - Native UIs
  : 각 OS에 특화된 application을 작성하기 위해 다른 UI layer를 사용 가능?
  : iOS (MonoTouch), Android (Android.Views), Windows Phone (XAML/Silverlight), Windows 8 (Metro APIs)

Code Reuse를  확대를 위해 다음의 sub-system들을 사용할 수 있다고 함.

  1. SQLite-NET for local SQL storage,
  2. Xamarin Plugins for accessing device-specific capabilities including the camera, contacts and geolocation,
  3. Using framework features for networking, web services, IO and more.



[Part 1 – Understanding the Xamarin Mobile Platform]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/

Mobile에서 app개발을 할 수 있도록 하는 Xamarin platform은 다음으로 구성됨.
 - C# language
 - Mono .NET framework :
 - Compiler : Target OS, Platform 대상으로 필요한 것들을 빌드하고 최적화도 수행
 - IDE tools : Xamarin Studio IDE, plugin for VS

Complication
 - iOS
  : AOT(Ahead-Of-Time) 컴파일을 통해 C# 코드에서 ARM assembly 결과물로 생성함
  : iOS는 runtime code generation을 허용하지 않아 제약 존재 (Xamarin.iOS Limitations)
 - Android
  : 컴파일을 통해 C# 코드에서 IL 결과물을 생성하고 MonoMV, JIT 컴파일러?와 함께 packaging됨. App은 JAVA/ART(Android RumTime)와 함께 실행되며 JNI를 통해 native type을 접근할 수 있음.
  : Android에서의 제약들( Xamarin.Android Limitations)
 - Windows Phone
  : C#은 IL로 컴파일 되어 build-in된 runtime에서 실행된다. 뭐 당연하겠지..

[IDE]

Development OS
Mac OS X
Windows
IDE
Xamarin Studio
Xamarin Studio
Visual Studio
iOS
Y
-
Y
Android
Y
Y
Y
Windows Phone
-
-
Y
Visual Studio 2015 Update 2 부터는 Xamarin 포함

 - iOS 개발 시 Mac OS X 필요

[UI]
 - 코드로 UI를 작성할 수 도 있고 Visual Designer를 사용해서 편하게 만들 수도 있음.
 - 하지만 각 OS의 metaphor(일반적인 Look and feel?)를 참고할 필요 있음.
  : iOS
   . hierarchical navigation with soft back button, tabs on the bottom of the screen.
   . Apple's Human Interface Guidelines
  : Android
   . hardware/system-software back button, action menu, tabs on the top of the screen.
   . Google's User Interface Guidelines
  : Windows Phone
   . hardware back button, panorama layout control, live tiles.
   . User Experience Design Guidelines for Windows Phone

[Library and Code Re-Use]
 - C# library야 당연히 사용할 수 있겠고
 - Objective-C Bindings + Binding Projects : btouch 제공
  : Binding Objective-C Types documentation
 - .jar Bindings + Binding Projects
  : Binding a Java Library documentation 
 - C via PInvoke
  : P/Invoke(Platform Invoke)를 사용하여 C#에서 native library들 사용이나 native library에서 callback 호출을 하게할 수 있음.
  :  linking native libraries

예시 - SQLite-NET
[DllImport("sqlite3", EntryPoint = "sqlite3_open", CallingConvention=CallingConvention.Cdecl)]
public static extern Result Open (string filename, out IntPtr db);
 - C++ via CppSharp
  : https://github.com/mono/CppSharp

[Part 2 - Architecture]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_2_-_architecture/

[OOP 개념]
 : 참고
  . 나무위키 객체 지향 프로그래밍
  . 객체지향 개념 (쫌 아는체 하기) http://www.slideshare.net/plusjune/ss-46109239
 - Encapsulation
 - Separation of Responsibilities
 - Polymorphism

[Application Layers]
 : 누가 정의했는지는 모르겠지만 용어는 알아두자.
 - Data Layer
  : SQLite 같은 DBMS가 여기에 해당 될듯
 - Data Access Layer
  : Data Layer를 사용(CRUD)하기 위한 wrapper/DAO 같은 부분?
 - Business Layer/Business Logic Layer
 - Service Access Layer
  : Cloud나 다른 web service들을 Application이나 UI layer에서 사용하기 위한 API들을 제공한다.
 - Application Layer
  : platform/application specific한 code를 포함하는 layer.
  : User Interface Layer와의 차이는 UI component를 포함하는지 여부와 다른 screen이나 device에 대해서 공유되는지 여부라고 함.
 - User Interface Layer
  : 사용자가 직접 대면하는 화면들(screens, widgets 등)을 관리하고 제공함.

[Common Mobile Software Patterns]
 - MVC(Model, View, Controller) pattern
 - Business Facade (Manager Pattern) pattern
  : 복잡한 처리를 간단하게 수행할 수 있도록 단순화된 entry point(ex API, etc?)를 제공함.
  : https://ko.wikipedia.org/wiki/%ED%8D%BC%EC%82%AC%EB%93%9C_%ED%8C%A8%ED%84%B4
 - Singleton pattern
 - Provider (Strategy) pattern?
  : http://hyeonstorage.tistory.com/146
 - Async pattern?
  : Async keyword는 아니며 보통 network 처리 같이 시간이 필요한 동작 수행 시 UI나 application이 pending되거나 영향을 받지 않도록 처리할 때 사용하며 주로 thread를 사용한다. 이 때 thread life cycle 관리, 수행 후 notification등을 고려해야 함.

[Part 3 - Setting Up A Xamarin Cross Platform Solution]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_3_-_setting_up_a_xamarin_cross_platform_solution/

처음에 설명된 PCL 방법을 쓰던지 Shared Project 방법을 쓰던지 간에 Xamarin에서는 Core project와 Platform-specific application project로 나뉜다.



Core Project
 : 플랫폼에 상관없이 재사용 가능한 코드들로 구성
 : Data Layer, Data Access Layer, Service Access Layer, business Layer 들이 존재

Platform-Specific Application Projects
 : platform-specific한 feature들을 사용하고 platform SDK과 binding된 코드들이 포함됨
 : Application Layer, User Interface Layer 들이 존재


[Part 4 - Dealing with Multiple Platforms]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_4_-_platform_divergence_abstraction_divergent_implementation/

Universal UI attributes
 - Feature selection via tabs or menus
 - Lists of data and scrolling
 - Single views of data
 - Editing single views of data
 - Navigating back

Platform-specific attributes
 - Screen sizes
 - Navigation metaphors
 - Keyboards
 - Touch and gestures
 - Push notifications

Device-specific features
 - Camera
 - Geo-location & maps
 - Accelerometer, gyroscope and compass
 - Twitter and Facebook
 - Near Field Communications (NFC)

[Platform Divergence를 처리하는 방법]
 - Platform Abstraction
  : Facade pattern을 사용해서 unified API를 제공하여 platform 특화된 구현부를 추상화하는 방법
  : Interface나 상속을 통해서 class를 추상화하는 방법
  : Xamarin.Forms
  : Cross-Platform Plug-ins

 - Divergent Implementation
  : Conditional compilation을 이용하여 platform에 특화된 부분을 처리하는 방법

[Platform Abstraction]
- Class Abstraction
 : Interface를 사용하거나 Inheritance을 통해 처리하거나

- Xamarin.Forms
 : A cross-platform UI toolkit that allows developers to easily create native user interface layouts that can be shared across Android, iOS, and Windows Phone.

- Plug-in Cross-Platform Functionality
 : https://github.com/xamarin/plugins

- Other Cross-Platform Libraries
 - MvvmCross - https://github.com/slodge/MvvmCross/
 - Vernacular (for localization) - https://github.com/rdio/vernacular/
 - MonoGame (for XNA games) - http://monogame.codeplex.com/
 - NGraphics - NGraphics and its precursor https://github.com/praeclarum/CrossGraphics

[Divergenct Implementation]
- Conditional compilation
#if __MOBILE__
// Xamarin iOS or Android-specific code
#endif

iOS

Xamarin.iOS defines __IOS__ which you can use to detect iOS devices.
#if __IOS__
// iOS-specific code
#endif
There are also Watch- and TV-specific symbols:
#if __TVOS__
// tv-specific stuff
#endif

#if __WATCHOS__
// watch-specific stuff
#endif

Android

Code that should only be compiled into Xamarin.Android applications can use the following
#if __ANDROID__
// Android-specific code
#endif
Each API version also defines a new compiler directive, so code like this will let you add features if newer APIs are targeted. Each API level includes all the ‘lower’ level symbols. This feature is not really useful for supporting multiple platforms; typically the __ANDROID__ symbol will be sufficient.
#if __ANDROID_11__
// code that should only run on Android 3.0 Honeycomb or newer
#endif

[Part 5 - Practical Code Sharing Strategies]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_5_-_practical_code_sharing_strategies/

필요할 때 참고하면 될 듯
DBMS, File System, Network, Web Services 관련 Solution들


[Part 6 - Testing and App Store Approvals]

https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_6_-_testing_and_app_store_approvals/


[Case Study: Tasky]

https://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/case_study-tasky/

2016년 4월 13일 수요일

[Links] Xamarin 관련 링크 모음, 설치

필요에 의해 Xamarin 관련 링크만 정리함.

Xamarin 사이트 및 소개
https://www.xamarin.com/
: http://www.slideshare.net/Xamarin/native-i-os-android-and-windows-development-in-c-with-xamarin-4

Getting Started
https://developer.xamarin.com/guides/android/getting_started/

Xamarin for Absolute Beginners
: 동영상 강의 기본적인 설치, 디버깅, 사용방법 관련
: https://mva.microsoft.com/en-US/training-courses/xamarin-for-absolute-beginners-16182?l=fPHWqptJC_5705846048

Xamarin 관련 PT들
http://www.slideshare.net/kmstechnology/cross-platform-mobile-development-with-c-and-xamarin
 . 실제 Xarmarin 전반 적인 내용과 pros and cons에 대해서 설명하고 있음.
http://www.slideshare.net/joekoletar/minnesota-entrprise-mobile-user-group-meeting
 . Xamarin 외 다른 Cross Platform 방법들과 비교

Xamarin Architecture
https://developer.xamarin.com/guides/android/under_the_hood/architecture/
: 간략한 Architecture 내용들. 사실 구글 이미지 검색하면 더 좋은 관련 이미지들이 나옴

Xamarin.Forms
https://www.xamarin.com/forms
: (동영상 소개) https://fast.wistia.net/embed/iframe/w2p6ayviev?popover=true
: (edX 온라인 강의) https://www.edx.org/course/introduction-xamarin-forms-microsoft-dev215x
: (Samples) https://developer.xamarin.com/samples/xamarin-forms/all/

Installation for Windows
https://developer.xamarin.com/guides/android/getting_started/installation/windows/

하지만 Xamarin 설치 시
Xamarin Unified Installer를 사용할 필요 없이
Visual Studio를 설치하면 Xamarin을 설치 할 수 있음.

확인은 Visual Studio Professional 2015 update 2 버전에서 확인하였으나
Visual Sutdio 2015 Community version에서도 Xamarin 설치 가능함. - https://www.visualstudio.com/products/visual-studio-community-vs

*Visual Studio Emulator for Android의 경우 "플랫폼 간 모바일 개발" > "일반 도구와 소프트웨어 개발 키트" > "Visual Studio Emulator for Android" 를 선택해서 함께 설치하면 되지만
혹시나 없으면 아래 링크에서 다운로드 하거나 Hyper-V 설치가 되어 있는지 확인 필요
 : 다운로드 : https://www.visualstudio.com/en-us/features/msft-android-emulator-vs.aspx
 : Hyper-V : https://technet.microsoft.com/ko-kr/library/hh846766.aspx#BKMK_Step1




C# Class 특성, 상속, 다형성 관련 정리

[C# Class 예제]


namespace ProgrammingGuide
{
    // Class definition.
    public class MyCustomClass
    {
        // Class members:
        // Property.
        public int Number { get; set; }

        // Method.
        public int Multiply(int num)
        {
            return num * Number;
        }

        // Instance Constructor.
        public MyCustomClass()
        {
            Number = 0;
        }
    }
    // Another class definition. This one contains
    // the Main method, the entry point for the program.
    class Program
    {
        static void Main(string[] args)
        {
            // Create an object of type MyCustomClass.
            MyCustomClass myClass = new MyCustomClass();

            // Set the value of a public property.
            myClass.Number = 27;

            // Call a public method.
            int result = myClass.Multiply(4);
        }
    }
}

[C# Class Features]

- C++과 다르게 struct는 값형식(복사시 값들이 복사 된다), class는 참조형식(복사시 참조만 복사 된다.) 
 : C#에서는 struct는 단지 값을 저장하기 위한 단순 용도로 사용해야 할 것 같음. 

- 접근 제한자로 public, private, protected, internal protected internal 이 있음

- Constructor, destructor 정의는 대부분 유사하고 상속된 클래스들의 destructor들은 자동으로 자식부터 부모 순으로 호출 됨.

- getter, setter를 위해 손쉬운 property라는 방법을 제공함

- 단일 상속만 허용
 : 하지만 인터페이스를 두개 이상 구현할 수 있음.

- 최상위 객체는 object 임

- 상속에서 virtual, override, sealed, new, abstract 등의 keyword들을 사용

[Access Modifiers, 접근 제한자]


일반적으로 public, private, protected만 봤었는데 어셈블리 레벨에서 접근을 제하하는 internal, protected internal 이 있음.

C# 한정자
정의

동일한 어셈블리의 다른 코드나 해당 어셈블리를 참조하는 다른 어셈블리의 코드에서 형식이나 멤버에 액세스할 수 있습니다.
동일한 클래스의 코드에서만 형식이나 멤버에 액세스할 수 있습니다.

동일한 클래스의 코드나 파생 클래스의 코드에서만 형식이나 멤버에 액세스할 수 있습니다.
동일한 어셈블리의 코드에서는 형식이나 멤버에 액세스할 수 있지만 다른 어셈블리의 코드에서는 액세스할 수 없습니다.

protected internal
동일한 어셈블리의 코드 또는 다른 어셈블리의 파생 클래스에서 형식이나 멤버에 액세스할 수 있습니다.

다음 예제에는 두 개의 파일 Assembly1.cs 및 Assembly1_a.cs가 포함되어 있습니다. 첫 번째 파일에는 내부 기본 클래스 BaseClass가 있습니다. 두 번째 파일에서 BaseClass를 인스턴스화하려고 시도하면 오류가 발생합니다.

// Assembly1.cs
// Compile with: /target:library
internal class BaseClass 
{
   public static int intM = 0;
}
// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess 
{
   static void Main() 
   {
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

[Constructor(생성자), Destructor(소멸자)]


Constructor, 생성자

 : 클래스 이름으로 표현, 반환 선언 없음.

- Default Constructor
 : 아무 매개변수를 가지지 않는 constructor.
 : 명시되지 않았을 경우 static constructor를 제외하고 컴파일러에서 자동 생성

- base
 : 상속한 부모 class의 constructor를 명시적으로 호출하거나(1) 자신의 default constructor를 호출할 때 사용(2)

(1) 상속 관계에서 부모(Employee)의 constructor를 호출하는 예제

public class Manager : Employee
{
    public Manager(int annualSalary)
        : base(annualSalary)
    {
        //Add further instructions here.
    }
}
(2) 자신의 default constructor를 호출하는 예제

public class Employee
{
    public int salary;

    public Employee(int annualSalary)
    {
        salary = annualSalary;
    }

    public Employee(int weeklySalary, int numberOfWeeks)
    {
        salary = weeklySalary * numberOfWeeks;
    }
}
다음 문 중 하나를 사용하여 이 클래스를 만들 수 있습니다.
Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);
생성자에서는 base 키워드를 사용하여 기본 클래스의 생성자를 호출할 수 있습니다.예를 들면 다음과 같습니다.
public class Manager : Employee
{
    public Manager(int annualSalary)
        : base(annualSalary)
    {
        //Add further instructions here.
    }
}

- this
 : 자신이 가진 constructor를 호출할 때 사용 가능

public Employee(int weeklySalary, int numberOfWeeks)
    : this(weeklySalary * numberOfWeeks)
{
}

- Private Constructor
 : Instance화가 필요없이 static member만 제공할 경우 사용하는 방법

class NLog
{
    // Private Constructor:
    private NLog() { }

    public static double e = Math.E;  //2.71828...
}

- Static Constructor
 : 정적 데이터를 초기화 하거나 생성자에서 수행하는 작업을 한번만 수행하기 위해서 사용 
 : 첫번째 인스턴스가 만들어지기 전이나 정적 멤버가 참조되기 전에 클래스를 초기화 하기 위해 자동으로 호출 됨.

class SimpleClass
{
    // Static variable that must be initialized at run time.
    static readonly long baseline;

    // Static constructor is called at most one time, before any
    // instance constructor is invoked or member is accessed.
    static SimpleClass()
    {
        baseline = DateTime.Now.Ticks;
    }
}

- Copy Constructor
 : C#에서는 Copy Constructor를 제공하지 않지만 아래와 같이 만들 수 있음.

class Person
{
    // Copy constructor.
    public Person(Person previousPerson)
    {
        Name = previousPerson.Name;
        Age = previousPerson.Age;
    }

    //// Alternate copy constructor calls the instance constructor.
    //public Person(Person previousPerson)
    //    : this(previousPerson.Name, previousPerson.Age)
    //{
    //}

    // Instance constructor.
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public int Age { get; set; }

    public string Name { get; set; }

    public string Details()
    {
        return Name + " is " + Age.ToString();
    }
}

Destructor, 소멸자

 : ~와 클래스 이름으로 표현, 접근제한자/반환/매개변수 선언 없음.
 : 클래스에서만 사용 가능하고 구조체에 정의할 수 없음.
 : 하나의 소멸자만 정의 가능, 상속/오버로드 불가
 : 상속관계에서 소멸자는 자식부터 부모순으로 호출 된다. 
 : 소멸자에서 자동으로 GC를 호출하므로 빈 소멸자는 정의 하지 않는 것이 추천 됨.

class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}
소멸자는 개체의 기본 클래스에서 암시적으로 Finalize를 호출합니다. 따라서 위의 소멸자 코드는 암시적으로 다음과 같은 코드로 변환됩니다.
protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}
즉, Finalize 메서드는 최대 파생 인스턴스부터 최소 파생 인스턴스까지 상속 체인에 있는 모든 인스턴스에 대해 재귀적으로 호출됩니다.
System_CAPS_note참고
빈 소멸자는 사용하지 않는 것이 좋습니다. 클래스에 소멸자가 포함된 경우 Finalize 큐에 엔트리가 만들어집니다. 소멸자가 호출되면 큐 처리를 위해 가비지 수집기가 호출됩니다. 그러므로 빈 소멸자는 성능 저하를 가져올 뿐입니다.

Object Initiailizer
 : https://msdn.microsoft.com/ko-kr/library/bb397680.aspx
 : 생성자를 명시적으로 호출하지 않고 선언적 방식으로 형식적 개체를 초기화 할 수 있음.
 : 적절한 생성자를 호출하고 없다면 기본 생성자 호출 후 멤버 초기화

public class Program
{
    public static void Main()
    {

        // Declare a StudentName by using the constructor that has two parameters.
        StudentName student1 = new StudentName("Craig", "Playstead");

        // Make the same declaration by using an object initializer and sending 
        // arguments for the first and last names. The default constructor is 
        // invoked in processing this declaration, not the constructor that has
        // two parameters.
        StudentName student2 = new StudentName
        {
            FirstName = "Craig",
            LastName = "Playstead",
        };

        // Declare a StudentName by using an object initializer and sending 
        // an argument for only the ID property. No corresponding constructor is
        // necessary. Only the default constructor is used to process object 
        // initializers.
        StudentName student3 = new StudentName
        {
            ID = 183
        };

        // Declare a StudentName by using an object initializer and sending
        // arguments for all three properties. No corresponding constructor is 
        // defined in the class.
        StudentName student4 = new StudentName
        {
            FirstName = "Craig",
            LastName = "Playstead",
            ID = 116
        };

        System.Console.WriteLine(student1.ToString());
        System.Console.WriteLine(student2.ToString());
        System.Console.WriteLine(student3.ToString());
        System.Console.WriteLine(student4.ToString());
    }

    // Output:
    // Craig  0
    // Craig  0
    //   183
    // Craig  116
}

public class StudentName
{
    // The default constructor has no parameters. The default constructor 
    // is invoked in the processing of object initializers. 
    // You can test this by changing the access modifier from public to 
    // private. The declarations in Main that use object initializers will 
    // fail.
    public StudentName() { }

    // The following constructor has parameters for two of the three 
    // properties. 
    public StudentName(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }

    // Properties.
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int ID { get; set; }

    public override string ToString()
    {
        return FirstName + "  " + ID;
    }
}

[Property, Setter, Getter]

 - get은 member 변수를 반환하고 set은 새 값을 할당하는데 사용

class TimePeriod
{
    private double seconds;

    public double Hours
    {
        get { return seconds / 3600; }
        set { seconds = value * 3600; }
    }
}


class Program
{
    static void Main()
    {
        TimePeriod t = new TimePeriod();

        // Assigning the Hours property causes the 'set' accessor to be called.
        t.Hours = 24;

        // Evaluating the Hours property causes the 'get' accessor to be called.
        System.Console.WriteLine("Time in hours: " + t.Hours);
    }
}
// Output: Time in hours: 24

 - 각가 다른 접근 제한자를 가질 수 있음.
  : get은 property의 기본 접근 제한자인 public 임

private string name = "Hello";

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}
 - value는 set 접근자에서 할당하는 값을 의미
 - set을 구현하지 않는 속성은 읽기 전용
 - set, get을 위한 별도 구현이 필요 없을 경우 아래 처럼 자동 구현 속성을 사용할 수 있음.

// This class is mutable. Its data can be modified from
// outside the class.
class Customer
{
    // Auto-Impl Properties for trivial get and set
    public double TotalPurchases { get; set; }
    public string Name { get; set; }
    public int CustomerID { get; set; }

    // Constructor
    public Customer(double purchases, string name, int ID)
    {
        TotalPurchases = purchases;
        Name = name;
        CustomerID = ID;
    }
    // Methods
    public string GetContactInfo() {return "ContactInfo";}
    public string GetTransactionHistory() {return "History";}

    // .. Additional methods, events, etc.
}

class Program
{
    static void Main()
    {
        // Intialize a new object.
        Customer cust1 = new Customer ( 4987.63, "Northwind",90108 );

        //Modify a property
        cust1.TotalPurchases += 499.99;
    }
}

[Inheritance(상속), Polymorphism(다형성)]


객체 지향 프로그래밍(Object-Oriented Programming)

 : 개념이 너무 방대하여 자세한 내용은 적지 못하고 위 링크를 참고....

Inheritance, 상속

 : 특정 클래스를 이용하여 새로운 클래스를 정의할 때 사용 되며 자식(파생) 클래스는 부모(기본) 클래스의 멤버를 접근 제한자에 따라서 접근할 수 있고 재정의 할 수 있다..


Polymorphism, 다형성


- Run-time에 자식 클래스는 다형성의 방법을 통해 부모 클래스의 형태로 처리 될 수 있고 이는 collection에 자식 클래스들을 넣고 처리할 경우 유용하다.

- 부모 클래스는 virtual method를 구현할 수 있고 이를 자식 클래스들에서는 재정의 하여 구현에서 자식 클래스의 종류에 상관없이 필요한 기능을 실행/사용 할 수 있다.

- 예제 설명
 : Shape라는 부모 클래스를 만들고 Rectanble, Circle 및 Triangle과 같은 자식 클래스를 만듭니다. 
 : Shape 클래스에 Draw라는 가상 메서드를 제공하고, 각 자식 클래스들에서 재정의하여 자식 클래스가 나타내는 특정 도형을 그림. 
 : 부모 클래스의 Shape 형태의 List<Shape> 개체를 만들고 Shape를 상속한 Circle, Triangle 및 Rectangle을 추가할 수 있음.
 : 화면을 업데이트하기 위해 foreach 루프를 사용하여 목록의 각 Shape 개체에서 가상 상속하고 있는 Draw 메서드를 호출합니다. 
  . 이 때 호출되는 목록의 형태는 Shape이더라도 호출되는 런타임 형식은 각 파생 클래스에서 재정의한 Draw 메서드입니다.


public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }

    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Polymorphism at work #1: a Rectangle, Triangle and Circle
        // can all be used whereever a Shape is expected. No cast is
        // required because an implicit conversion exists from a derived 
        // class to its base class.
        System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>();
        shapes.Add(new Rectangle());
        shapes.Add(new Triangle());
        shapes.Add(new Circle());

        // Polymorphism at work #2: the virtual method Draw is
        // invoked on each of the derived classes, not the base class.
        foreach (Shape s in shapes)
        {
            s.Draw();
        }

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

}

/* Output:
    Drawing a rectangle
    Performing base class drawing tasks
    Drawing a triangle
    Performing base class drawing tasks
    Drawing a circle
    Performing base class drawing tasks
 */


- virtual, override
 : 부모 클래스는 자식 클래스가 재정의 할 수 있도록 virtual로 명시함.
  . virtual method가 호출 되면 개체의 run-time 형식이 검사 됨.
  . virtual 한정자는 static, abstract, private, override 한장자와 함께 사용 불가

 : 자식 클래스는 Rum-time시 가상 호출이 될 수 있도록 override를 명시함.
  . override로는 virtual, abstract, override 속성의 method를 재정의 가능하지만 non virtual, static 속성의 method는 재정의 불가
  . virtual method의 접근 제한자를 변경 할 수 없음.

public class BaseClass
{
    public virtual void DoWork() { }
    public virtual int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public override void DoWork() { }
    public override int WorkProperty
    {
        get { return 0; }
    }
}

 : 자식 클래스가 부모 클래스의 instance로 사용 되는 경우에도 override된 method가 호출 됨.

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Also calls the new method.

- new
 : 상속된 부모 클래스의 member를 숨길 경우 사용

public class BaseClass
{
    public void DoWork() { WorkField++; }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}

public class DerivedClass : BaseClass
{
    public new void DoWork() { WorkField++; }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}
 : 부모 클래스로 캐스팅하여 부모 클래스의 method를 호출 가능

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

- sealed
 : 상속된 클래스간에 가상 상속은 무제한으로 가능함.
 : 자식 클래스에서 더이상의 가상 상속을 방지하기 위해서는 sealed를 선언함.

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

public class C : B
{
    public sealed override void DoWork() { }
}

- base
 : 자식 클래스에서 부모 클래스의 method나 속성에 접근할 때 사용

public class Base
{
    public virtual void DoWork() {/*...*/ }
}
public class Derived : Base
{
    public override void DoWork()
    {
        //Perform Derived's work here
        //...
        // Call DoWork on base class
        base.DoWork();
    }
}

- abstract
 : abstract 클래스에 포함된 abstract 멤버는 파생되는 자식 클래스에서 구현되어야 함.
 : abstract 클래스는 인스턴스화 될 수 없음.
 : abstract 클래스는 seal 한정자와 함께 사용 불가 (의미가 상충)
 : abstract method는 abstract class에서만 허용
 : virtual method와 abstract method의 차이점
   . static 속성에는 abstract 한정자 사용 불가
   . 상속된 abstract 속성은 override 한정자를 사용하여 자식 클래스에서 재정의 가능

abstract class ShapesClass
{
    abstract public int Area();
}
class Square : ShapesClass
{
    int side = 0;

    public Square(int n)
    {
        side = n;
    }
    // Area method is required to avoid
    // a compile-time error.
    public override int Area()
    {
        return side * side;
    }

    static void Main() 
    {
        Square sq = new Square(12);
        Console.WriteLine("Area of the square = {0}", sq.Area());
    }
}

- is
 : 객체가 주어진 형식에 맞는지 확인할 수 있음.
 : Run-time 시 확인 가능하고 true/false 리턴
 : reference conversions, boxing/unboxing conversions에만 허용됨.

class Class1 {}
class Class2 {}
class Class3 : Class2 { }

class IsTest
{
    static void Test(object o)
    {
        Class1 a;
        Class2 b;

        if (o is Class1)
        {
            Console.WriteLine("o is Class1");
            a = (Class1)o;
            // Do something with "a."
        }
        else if (o is Class2)
        {
            Console.WriteLine("o is Class2");
            b = (Class2)o;
            // Do something with "b."
        }

        else
        {
            Console.WriteLine("o is neither Class1 nor Class2.");
        }
    }
    static void Main()
    {
        Class1 c1 = new Class1();
        Class2 c2 = new Class2();
        Class3 c3 = new Class3();
        Test(c1);
        Test(c2);
        Test(c3);
        Test("a string");
    }
}
/*
Output:
o is Class1
o is Class2
o is Class2
o is neither Class1 nor Class2.
*/

- as
 : 변환 가능한 reference 형식으로 변환하거나 nullable 형식으로 변환함.
 : as는 cast와 유사하며 변환이 불가할 경우 exception을 발생하지 않고 null을 리턴함.

class ClassA { }
class ClassB { }

class MainClass
{
    static void Main()
    {
        object[] objArray = new object[6];
        objArray[0] = new ClassA();
        objArray[1] = new ClassB();
        objArray[2] = "hello";
        objArray[3] = 123;
        objArray[4] = 123.4;
        objArray[5] = null;

        for (int i = 0; i < objArray.Length; ++i)
        {
            string s = objArray[i] as string;
            Console.Write("{0}:", i);
            if (s != null)
            {
                Console.WriteLine("'" + s + "'");
            }
            else
            {
                Console.WriteLine("not a string");
            }
        }
    }
}
/*
Output:
0:not a string
1:not a string
2:'hello'
3:not a string
4:not a string
5:not a string
*/