LoginSignup
2

More than 3 years have passed since last update.

Xamarinで動的に機能追加できるか試してみた

Posted at

以前、Silverlight の Out of Browser で動くアプリ作っていたのですが、xapファイルをWEBサーバー上に置いて動的に機能の追加をしたりしてました。

そういったことが Xamarin でも可能なのか試してみました。
調べたらだいぶ前に既に試された方いるようですけど、せっかく試したので投稿します → https://forums.xamarin.com/discussion/2294/assembly-load-is-it-possible

結論

最初に結論です。

iOSは無理です

Androidは条件により可能です

とりあえず、業務で利用されるのはお勧めはしません。

作ってみる

こんなコードになりました。


        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            Device.BeginInvokeOnMainThread(async () =>
            {
                try
                {
                    await Task.Delay(1000);
                    var file = await LoadDLL("https://dllを置いてるサーバー/SampeClassLibrary.dll");
                    var assembly = Assembly.LoadFrom(file.FullPath);
                    // 読み込みたいクラスを読み込む
                    dynamic instance = assembly.CreateInstance("SampeClassLibrary.Flash");
                    // 今回のサンプルクラスはShowというメソッドを持っている
                    instance.Show(1000, Root);
                }
                catch (Exception e)
                {
                    await DisplayAlert("Error", e.ToString(), "OK");
                }
            });
        }

        public static async Task<IFile> LoadDLL(string url)
        {
            // NetStandardStorageを使ってdllをローカルに1回保存
            var folder = CrossStorage.FileSystem.LocalStorage;
            var file = folder.CreateFile("dynamictest.dll", Plugin.NetStandardStorage.Abstractions.Types.CreationCollisionOption.ReplaceExisting);
            HttpClient client = new HttpClient();
            var response = await client.GetAsync(url);
            byte[] body = new byte[1024 * 1024];
            using (var stream = await response.Content.ReadAsStreamAsync())
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    var length = stream.Read(body, 0, body.Length);
                    if (length > 0)
                    {
                        ms.Write(body, 0, length);
                    }
                    else
                    {
                        break;
                    }
                }
                file.WriteAllBytes(ms.ToArray());
            }
            return file;
        }

検証してみる

実際に動かしてみます

iOS

iOSはシミュレーターでは動きましたが実機では無理でした。
理由は iOS は AOT(Ahead-Of-Time) のためです。
中途半端な知識で書くと嘘になるかもしれないので、ここでは AOT については説明しません。
詳しくは検索してみてください。

Android

私の環境のシミュレーターが起動できなかったのでシミュレーターでは試していませんが、実機で動くことを確認しました。
ストア経由で配布した場合でも動くかどうかは不明です。

最初に「条件により」と書いたのは、Android でも AOT コンパイルのオプションがあるので AOT の場合は無理なんじゃないかと予想してます。
Visual Studio がエンタープライズ版じゃないと試せないので今回は確認していません。

諸々バージョンや依存関係等考えると、実際にこれを運用するのは大変そうだなと思います。

まとめ

動的に機能追加/修正したい場合は、おとなしく WebView 使うとか、ReactNative+Expo 使うとかを検討した方が良いかと思いました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2