unity側からUWP側の機能をつかうコツ

#UWP側の機能で実装が必要な時困ったこと
unity側からUWPのライブラリを使おうとすると「どうやってするんだ？」となり結果としていろいろ試行錯誤してこういう方法？というのを少し試してみました。
もっとこうしたらできるよなどありましたら教えていただけると嬉しいです。

## 環境
今回使用した環境は以下の通りです。
Windows 10 Pro
Visual Studio 2015 Community Edition update 3
Unity 5.5.0P2 Personal

## 現在での自分の理解

- UWP側、Unity側のライブラリはそれぞれの中でしか使ってはいけない（極力）
- Unity側のC#のコードはクロスプラットフォームを意識して使用できる機能に制限がある

## アプリを作るにあたっての前提

- Unity側のビルドは何度もする
- Unityのコードは出力しない。

## サンプルコード
簡単ですがサンプルのコードをアップしました。
https://github.com/TakahiroMiyaura/UWPBridgeSamples

## コードの説明
考え方としては、UWP側で実装した機能（クラス）をUinity側のStaticな領域で管理しておいて必要に応じてUnity側でそこからオブジェクトを取得するというものです。
サンプルのコードではUnityで作った3DTextに表示する文字をUWP側で作ったクラスから取得します。
この際中継する管理クラスをUnity側に作成します。

### Unity側
#### 管理クラスの実装
オブジェクトを管理するUWPBridgeServiceクラスを作りました。
中には特に特殊なこともしていません。必要な機能としてはオブジェクトを管理するフィールドとオブジェクトの登録及び取得するメソッドだけになります。
これに加えてこの管理クラスに登録するオブジェクトに対して実装するインターフェースも併せて用意します。

```antlr-c#:UWPBridgeService.cs
// Copyright(c) 2017 Takahiro Miyaura

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class UWPBridgeService : MonoBehaviour
{
    private static List<IUWPBridgeService> _serviceCollection;

    private static readonly object LockObject = new Object();

    public static void AddService<T>(IUWPBridgeService service) where T : IUWPBridgeService
    {
        lock (LockObject)
        {
            if (_serviceCollection == null)
                _serviceCollection = new List<IUWPBridgeService>();
            _serviceCollection.Add(service);
        }
    }

    public static T GetService<T>() where T : IUWPBridgeService
    {
        return _serviceCollection.OfType<T>().FirstOrDefault();
    }

    public interface IUWPBridgeService
    {
    }
}
```
#### UWP側の部品を呼ぶための実装
今回は3DTextに文字を設定する機能をつくります。
Unity側ではUWP側で実装するためのインターフェースを用意します。
最初にこのインターフェースで登録されているオブジェクトを先の管理クラスから取得します。
取得後に文字列を取得するメソッドを呼び出し3DTextに対して値をセットします。

```antlr-c#:SetSampleText.cs
// Copyright(c) 2017 Takahiro Miyaura

using UnityEngine;

public class SetSampleText : MonoBehaviour
{
    public ISetSampleTextService service;

    public GameObject Text3D;


    // Use this for initialization
    private void Start()
    {
        // Initialize Service From UWP.
        service = UWPBridgeService.GetService<ISetSampleTextService>();
    }

    // Update is called once per frame
    private void Update()
    {
        //If Service is not Initialize,Call 'Start()'.
        if (service == null)
            Start();

        //Call Service.
        var textMesh = Text3D.GetComponent<TextMesh>();
        textMesh.text = service.GetText();
    }

    //ISetSampleTextService is interface for class create on UWP Project. 
    public interface ISetSampleTextService : UWPBridgeService.IUWPBridgeService
    {
        // Get string for 3DText.
        string GetText();
    }
}
```
### UWP側
Unity側で作ったISetSampleTextServiceを実装したクラスを作成します。
今回は単に文字列を返す実装を行いました。

```antlr-c#:SetSampleTextService.cs
namespace UWPBridgeSamples
{
    public class SetSampleTextService : SetSampleText.ISetSampleTextService
    {
        public string GetText()
        {
            return "Sample Text For UWP";
        }
    }
}
```

最後にアプリ起動時の最初の方で、以下の実装を行いSetSampleTextServiceを登録します。

```antlr-c#
UWPBridgeService.AddService<SetSampleText.ISetSampleTextService>(new SetSampleTextService());
```
## その他

UnityとUWPでの実装のセオリーがいまいちわかっていないため、備忘録的に書きました。
いろいろ探し回るとイベントでやるパターンが多いようです。ただイベントで作っていくと
自分の中では機能単位で管理しにくいんじゃないのかなと思うところもあって
機能単位でクラスをつくる今回の方法で試してみました。