【.NET Standard】SharedPropertyでアプリケーション設定を保存する

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">【告知】Xamarin.Formsの<a href="https://t.co/eC46vr1kqi">https://t.co/eC46vr1kqi</a>を強くしたようなもの(自称)としてSharedPropertyを公開しました～<br>内部的にはUtf8JsonかSpanJsonを使うようにしてます。<br>.NET Standard 2.0で作ってるのでアプリケーションデータを保存する際にぜひ使ってくださいm(__)m<a href="https://t.co/VWeI7FDhSW">https://t.co/VWeI7FDhSW</a></p>&mdash; Kペンギン (@penguin_sharp) <a href="https://twitter.com/penguin_sharp/status/1019003863116869632?ref_src=twsrc%5Etfw">July 16, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

~~作者直々の宣伝です~~

## はじめに
皆さん、アプリケーションの設定を保存する際どのようにするか迷ったことはありませんか？

自分はあります。

アプリケーションデータを保存するのって結構プラットフォーム依存なとこがあって、Xamarin.Nativeでは[Setting.Plugin](https://github.com/jamesmontemagno/SettingsPlugin)とか、Xamarin.Formsでは[Application.Current.Properties](https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/application-class#properties-dictionary)とかで、保存することになるかと思いますが、これらはプラットフォームごとの実装をしています。

時代はそろそろ.NET Standardだと思いますし、.NET Standardならプラットフォームのことなんか考えたくないところです。
[Akavache](https://github.com/reactiveui/Akavache)という良さげなライブラリがすでにありますが、これはSQLite3を使っていたりJson.NETを使っていたりと、すこし大げさな感じがします。

というわけがあったりして、軽量で.NET Standardなアプリケーション設定保存ライブラリーを作ってしまったという感じです。

## 使い方
NuGetで以下のどちらかをいれてください。必要なものは自動的に付いてくるはずです。

- [SharedProperty.Serializer.Utf8Json](https://www.nuget.org/packages/SharedProperty.Serializer.Utf8Json/)
- [SharedProperty.Serializer.SpanJson](https://www.nuget.org/packages/SharedProperty.Serializer.SpanJson/)

名前で気づくかと思いますが、内部的には[Utf8Json](https://github.com/neuecc/Utf8Json)または[SpanJson](https://github.com/Tornhoof/SpanJson)を使うようにしています。
基本的にはUtf8Jsonのほうを使うかと思いますが、.NET Core 2.1用にSpanJsonにも対応させています。

### 基本的な処理

```csharp
var sharedDictionary = new SharedDictionary(Utf8JsonSerializer.Default, IsolatedFileStorage.Default, null);
// Storageに保存されている設定を読み込む
await sharedDictionary.LoadFromStorageAsync();

// もちろん基本データ型の保存はできて
sharedDictionary.SetProperty("text", "sssss");
sharedDictionary.SetProperty("number", 1234);

// Utf8JsonまたはSpanJsonによって、ユーザー定義型の保存もできる
sharedDictionary.SetProperty("data", new Data());

// Storageに書き込む
await sharedDictionary.SaveToStorageAsync();

// 設定を読み込む
string text = sharedDictionary.GetProperty<string>("text");
int number = sharedDictionary.GetProperty<int>("number");
var data = sharedDictionary.GetProperty<Data>("data");
```

APIを見ればなんとなくわかるかとおもいます。

`SharedDictionary`のコンストラクターの第1引数には`Utf8JsonSerializer`か`SpanJsonSerializer`を渡すようにしてください。第2引数を`IsolatedFileStorage`にすることによって、.NET Standardがアプリケーション固有の領域に保存してくれます。

### 難読化と暗号化
アプリケーション設定を保存する際に、ある程度需要のある難読化 or 暗号化ですが、必要そうなのでできるようにしておきました。

`SharedDictionary`の第3引数がそれらの設定する場所で、難読化なら`SimpleConverter`を、暗号化なら`AesCryptoConverter`とか`RijndaelCryptoConverter`を渡してあげてください。

### Xamarin.iOS
もし、Xamarin.iOSでも利用するならUtf8Jsonのコードジェネレートが必要になります。[SharedPropertyのREADME](https://github.com/MeilCli/SharedProperty/blob/master/README-ja.md#xamarinios)に少し書いておきましたが、Xamarin.iOSで使う場合はいろいろとやらないといけないことがあるのだと留意してください。

## おわりに
結構省いたシンプルな説明にしたので、詳しくは[README](https://github.com/MeilCli/SharedProperty/blob/master/README-ja.md)を見てください。Issue/PRなどあれば受け付けてますので、遠慮なく投げてください！

詳しい作成背景とかは[個人ブログ](https://blog.meilcli.net/2018/07/cxamarinformsapplicationcurrentproperti.html)のほうに書いたので気になれば見てください。

[ConcurrentSharedDictionary](https://github.com/MeilCli/SharedProperty/blob/master/SharedProperty.NETStandard/ConcurrentSharedDictionary.cs)については非常に雑な実装をしたと思ってるので、もう少しまともな実装を思いついた方はご連絡お願いしますm(__)m