20200325のC#に関する記事は6件です。

.Net Core 3.1のコンソールアプリを、単一実行可能ファイルかつRuntimeのインストールなしでUbuntu 18.04で実行する

Publish Single Fileとself-containedを試してみたので、やったことの備忘です。

下記の記事を参考にしながら進めました。
.NET Core CLI を使用して .NET Core アプリを発行する
.NET Core 3.0のPublish Single File概要

前提

やりたいこと

  • .Net Core 3.1のコンソールアプリをUbuntu 18.04で実行したい
  • Ubuntu 18.04に.Net Core 3.1のRuntimeをインストールしたくない
  • 管理が面倒なので、単一実行可能ファイルにしたい

環境

開発環境
- Windows 10
- Visual Studio 2019

実行環境
- Ubuntu 18.04

実装方法

1. コンソールアプリを作る

Visual Studioのテンプレートからコンソールアプリを選び、ソリューションを作成します。
動くことが確認できればいいので、1秒ごとに「Hello World!」と出力するようにProgram.csを修正しました。

Program.cs
using System;
using System.Threading;

namespace SingleFileConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine("Hello World!");
                Thread.Sleep(1000);
            }
        }
    }
}

2. アプリケーションを発行する

  1. 開発者用コマンドプロンプトを起動する
    • ツール(T) > コマンドライン(L) > 開発者用コマンドプロンプト(C)
  2. dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=trueを実行する
  3. 実行ファイルが発行されていることを確認する(画像参照) 発行先.PNG

3. アプリケーションを実行する

  1. Windows 10で開発したアプリケーションを、Ubuntu 18.04にコピー
  2. ターミナルを立ち上げて、アプリケーションを配置したディレクトリまで移動
  3. chmod +x SingleFileConsoleでアプリケーションを実行可能形式にする
  4. ./SingleFileConsoleでアプリケーションを実行する

うまくいっていれば、下記の画像のように動作するはずです。
動作チェック.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PlayFab] データをクラウドセーブしたい時のAPIの選び方

前置き

  • クラウドにファイルをセーブする機能を実装するために関連するPlayFabの仕様を調べました
  • 2019/Dec時点の仕様です。調べてから時間が空いてますが書く時間が取れたので記事にしたということで。
  • 実装自体は大きくつまづく箇所もなく、リリース済みアプリ内で利用中です。

2系統のAPI

クラウドセーブを実装する場合に使うことになるPlayFab提供APIは、大きく分けると2つの系統があります。クラシックとエンティティEntityです。

クラシックAPIの特徴

  • 「ユーザー1人あたり」がサイズ制限になっていることが多い
  • ファイルを扱う場合はstringに変換する必要がある
  • 2018年以前はこの系統のAPIのみが提供されていたので系統名がなかった。Entityが登場したのでクラシックと呼ばれることに。本命登場で幼なじみと呼ばれるようになった感ある。

Entity APIの特徴

  • 2018年に導入されたAPI
  • JSONファイルやオブジェクトを直接扱える
  • 「アプリ全体が利用している量」がサイズ制限になっていることが多い
  • PlayFabは、同じことができる場合こちらを使うことを推奨している

2つのAPIをTier毎に比較

ESSENTIAL Tier PRO/Indie Tier
クラシック API 10000Byte/ユーザー※ (運営に相談/ユーザー)
Entity API 1GB/プロジェクト 50TB/プロジェクト
  • プロジェクトに必要なスペック&財布に応じて選ぶといいと思います
  • ※だいたい10000byteでなく、本当にきっちり10000byteです1byteでも超えていると、超えているのではじきましたというメールまで届きます。ちょっとくらい超えても大丈夫かなと淡く期待していましたがそんなことなかったです。

Tier

PlayFabの料金プランはTierで分かれている

ESSENTIAL 無料
Indie/PRO 有料 月99$/299$
ENTERPRIZE 有料、法人向け

※IndieはMAU10万超えでPROに自動移行、受けられるサービスは同じ
詳しい記事 => PlayFab 各プランのAPI制限値とか比較してみた

どちらを選んだか

  • 自分は、Essential Tierで利用中で、ユーザー数がどこまで増えるのか予測が難しかったので、10000byteと極小容量ですがユーザー数が増えても同容量使えるクラシックAPIを選びました。実際にどんなコードを組んでいるのかも時間がある時に記事にします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

null安全とLINQ

前書

流石にLINQまでフロー解析はしてくれないらしい

直面した場面

public static int? ToIntOrNull(int num)
{
    return num % 2 == 0 ? (int?)null : num;
}

//
public static IEnumerable<int> TestFunc1()
{
    //kは非nullが確定しているが警告が出る
    //CS8629    Null 許容値型は Null になる場合があります。
    return Enumerable.Range(0, 10)
        .Select((i) => ToIntOrNull(i))
        .Where((j) => j != null)
        .Select((k) => (int)k);
}
public static IEnumerable<int> TestFunc2()
{
    //!演算子をつければ警告は出ない
    return Enumerable.Range(0, 10)
        .Select((i) => ToIntOrNull(i))
        .Where((j) => j != null)
        .Select((k) => (int)k!);
}

追記

コメントを頂いたのでそのまま転記
OfType()を使えばすっきり綺麗に書けるそうです

public static IEnumerable<int> TestFunc3()
{
    return Enumerable.Range(0, 10)
        .Select((i) => ToIntOrNull(i))
        .OfType<int>();
// 1,3,5,7,9
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dotnet coreにおけるhttp proxy設定に関する注意点

はじめに

dotnet coreの2.1と3.0以降で、System.Net.Http.HttpClientのデフォルトhttpプロキシに関する挙動が異なるところがあったので記述する。

dotnet core 3.0以降

正式な仕様としては https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.defaultproxy?view=netcore-3.1 に記載がある。訳すと、

  • 明示的な指定がない場合、全てのプラットフォームで環境変数の値をまず確認する
    • http_proxy,https_proxy,all_proxy,no_proxyの三つ(大小文字問わず)
  • ない場合は、OSごとに処理が異なる
    • linuxはプロキシなしとして扱う
    • winはOS設定(winhttpとwininetの設定)を使用する
      • winhttpとwininetの両方で設定があった場合、wininetの方の設定が優先される
    • macはOS設定を使用する

dotnet core 2.1

HttpClient.DefaultProxyは2.1に存在しないため他にないか探したが、ドキュメントには存在しなかった。
自分で調べた結果、まとめると、

  • linuxの場合は環境変数のみ
  • winの場合は環境変数は無視され、OS設定(winhttp,wininet)を使用する
  • macの場合はシステム設定は無視され、環境変数のみ使われる

という具合のようだ。

主な差異

  • winの場合、netcoreapp3.0の時は環境変数を優先して使用するが、netcoreapp2.1では考慮もされない
  • linuxの場合は挙動は同じ
  • macの場合は、netcoreapp2.1ではOS設定が無視される

まとめ

プロキシ設定というのは見過ごされやすい盲点になるので、挙動の違いは把握しておきたい。
特にmacは持ってないのでソースベースの解析になるが、間違っていたら指摘希望。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更ながらWPFに置き換えてみる(8)

画面の右上、右下にWindowを飛ばすボタンをテスト。

アイコン化→通常Windowへ復帰した場合、画面の上限、右端、下限に接している場合現状のtop,leftを固定せずに拡大方向を切り替えてどのように見えるかを確認してみた。

TestApp3-2.gif

Windowの位置、サイズについては直接this.left、this.topをセットするというのが一番単純な方法ですが、それだと最低でも2ステップの実行となってしまいトランジション中にがたつきが目立つので、Win32のSetWindowPosでまとめてセットするように変更。

Windowの位置変更は非常に速いが、サイズの変更は予想通り処理が重い。
位置変更トランジションは中間に100ステップ入れていますがほとんど瞬間移動しているように見えます。
サイズの変更は30ステップ程度でタイミング的に釣り合うイメージでした。

新たに出てきた問題点
・Windowの位置変更にDragMoveを利用しているが、ドラッグ中のスクリーン枠へのスナップがForms+VBの時のように簡単にいかない(気がする)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VB6→C#化における、ラッピング戦略

コンバートしたソースを最大限利用する方法

プロジェクトの参照で、C# WinFormsプロジェクトの基本的な参照のみを残し、削除する
これにより、コンバート時に変換された、VB6互換部品のコードが全てエラーになる。
(詳細は、後日追記する)

SharpDevelopで新たに追加された、MyApplicationなどのStatic対応も全て使わないことにする。
参考にすることはある可能性はあるので、ファイル全体をコメントアウトしておく。

Using句のネームスペース設定中、Microsoft.VisualBasic 名前空間、Microsoft.VisualBasic.Compatibility.VB6 名前空間は参照を削除したことによって赤いアンダーラインが表示されるが、残しておく。この名前空間を利用し、エラーになっている部分を拾うことになる。

https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.compatibility.vb6?view=netframework-4.8

https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic?view=netframework-4.8

一部、LenBやErr()など、上記の名前空間に属する関数などが省略された形で記述されているが、
一括変換又は、下記で記述するマイグレーションサポート用のクラスへ実装することにする。詳細は後述する。
簡単に説明すると、この関数らを含むフォームを継承したクラスを作り、全てのフォームはそれらを継承するようにする。
Class MigSupForm : Form
{
LenB(){};
Err();
}
Class FrmXXX : MigSupForm
{

}
Grid

AxMSFlexGrid
MSWinsockLib
axWinsck
ADODB

これらのOCX部品に関しても、Microsoft.VisualBasic 名前空間、Microsoft.VisualBasic.Compatibility.VB6 名前空間へ属する
関数として作ることにより、変換ソースを極力修正しないようにする。

名前空間を利用する目的としては、一行一行の手間を省くためである。これは、実際やっていただければ納得するはず。

ここまでは無難な作業である。なんでやるかは、
VB6関連ソースを一括に管理するため、
移行の土台に素早く乗らせるため、
リファクタリングを活用することで、もっと効率的な作業を進めるため。
。。。

型の曖昧さの問題は、演算子周りで起きており、キャストを施すのは、最終的に道ではあるが、全てを手作業するのは大変である。
この解決策として、演算子のオーバーロードを施す事はどうだろうか。
全ての形ではない問題が起きている型のみを作成することにする。

ジェネリックも応用できそう
https://ufcpp.net/study/csharp/sp2_generics.html

BOXING、UNBOXINGも応用できそう。
オブジェクト型には全てが入る。
using System;

class Test
{
static void Main() {
int i = 123;
object o = i; // Boxing
int j = (int)o; // Unboxing
}
}

頻発する、Form を Objectへ代入、ShortにIntを代入 は
VBSObject クラス、VBSShortクラスを作り、演算子を定義すればそうだろうか。

全体的にStaticとなっているので、最初は、SharpDevelop作成サポートクラスに似せた
静的サポートクラスを作成する。ここにMain関数も入れておく。

フォームのクラス名でそのまま利用などは、SharpDelelop作成クラスでの定義を利用するように変換されているので、
それに似せるような形をとる。

win32 C# 関数 
ちょっと変換が変なので、見直しが必要。
https://www.atmarkit.co.jp/ait/articles/0305/09/news004.html

ここで結構調べられる
https://www.pinvoke.net/index.aspx

配列 コントロール C#
http://tki.main.jp/hata/indexer.html

このコンセプトのファイルは、DLLのプロジェクトにして、共通としてインポートするといいでしょう。

全体を早く見渡し、少しでも早く軌道に乗せたい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む