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

Rx風メソッドチェーンの定義方法

概要

Rx的なメソッドチェーンの定義方法について書きます。
あくまでも自分用の備忘録なので、細かい説明は書きません。

後日、気が向いたら書きます。

使い方

test.cs

//Class only
public class Observe<T> {
    private T result{ get; }
    public Observe(T initial) => result = initial;
    public Observe<TR> Operation<TR>(Func<T, TR> function) => new Observe<TR>(function(result));
    public void End(){}
}

public static class Observe{
    public static Observe<T> Start<T>(Func<T> initial) => new Observe<T>(initial());
}

//Class included interface
public interface IObserve<T> {
    IObserve<TR> Operation<TR>(Func<T, TR> function);
    void End();
}

public class Inheritance<T> : IObserve<T>{
    private T result { get; }
    public Inheritance(T initial) => result = initial;
    public IObserve<TR> Operation<TR>(Func<T, TR> function) => new Inheritance<TR>(function(result));
    public void End(){}
}

public static class Inheritance {
    public static IObserve<T> Start<T>(Func<T> initial) => new Inheritance<T>(initial());
}

//How to use
public class Hoge {
    public void Fuga() {
        Observe.Start(() => 1).Operation(x => x++).End();
        Inheritance.Start(() => 1).Operation(x => x++).End();
    }
}

追記:
Rx風とまでは行きませんが、下のコードでもそれっぽいことができます。

test.cs
public static class Chain {
    public static TR MethodChain<T, TR>(this T value, Func<T, TR> function) => function(value);
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#からPythonスクリプトを呼び出す

はじめに

唐突に画像と動画を加工してみたくなり、VisualStudio2017でPython3/OpenCVを使ってみました。

普段はC#を使っているので、使い慣れたC#からPythonスクリプトを呼び出せないか試してみました。

参考資料

下記のサイトを参考に実装しています。
Inter-process communication between C# and Python

実装方法

言語 実装する処理
Python 「第1引数の値」 + 「第2引数の値」 を出力する
C# 「第1引数の値」と「第2引数の値」を指定して、Pythonスクリプトを呼び出し、結果を出力する

1. Python側を実装

AdditionSample.py
import sys

if len(sys.argv) == 3:
    firstArgument = int(sys.argv[1]) 
    secondArgument = int(sys.argv[2])
    print(firstArgument + secondArgument)
else:
    print('ArgumentException...')

2. C#側を実装

Sample.cs
class Program
{
    static void Main(string[] args)
    {
        //VisualStudioが利用しているインタープリターのパス
        var pythonInterpreterPath = @"C:\sample\path\Anaconda3\python.exe";

        //「1. Python側を実装」にて保存したスクリプトのパス
        var pythonScriptPath = @"C:\sample\path\AdditionSample.py";

        var arguments = new List<string>
        {
            pythonScriptPath ,
            "10",   //第1引数
            "20"    //第2引数
        };

        var process = new Process()
        {
            StartInfo = new ProcessStartInfo(pythonInterpreterPath)
            {
                UseShellExecute = false,
                RedirectStandardOutput = true,
                Arguments = string.Join(" ", arguments),
            },
        };

        process.Start();

        //python側でprintした内容を取得
        var sr = process.StandardOutput;
        var result = sr.ReadLine(); 

        process.WaitForExit();
        process.Close();

        Console.WriteLine("Result is ... " + result);
    }
}

実行結果

Result is ... 30

感想

この方法を使えば、C#とPythonを組み合わせた実装ができそうです。

しかし、この方法だとPython側でprintした内容を受け取ることしかできないようです。
また、指定したPythonスクリプトを実行するだけなので、自由にPython側の処理を呼べるというわけでもありません。

処理内容にもよると思いますが、Python側をWebAPI化して、処理結果をJSON形式で結果を返すのが一番使いやすそうな気もします。

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

UnityのいろいろなTips

はじめに

当たり前に設定していることでも忘れてしまうことがよくあるので備忘録もかねて記事にしました。

Unityのバージョンは、2017.4 を基準に作成してあります。

画面サイズを変更するとUIが崩れる

Canvas Scalerが"Constant Pixel Size"になっているのが原因。

下の画像のように"UI Scale Mode"を"Scale With Screen Size"にするとよい。

また、"Reference Resolution"にはメインで使用する解像度を指定しておく。

※ただし、アスペクト比を変える場合はここの設定だけでは不十分

スマートフォンの複数バージョン対応や、縦横持ち対応などのアスペクト比を変えた場合のUIの設計は、

Unity公式ドキュメントに 複数解像度のためのUI設計 がありますので、そちらを参照ください。
cc9009570527503c5835bc7e32f476e0.png

スクリプト上でUIを生成した時に原点がずれる

例えば、

Image img = new GameObject("img").AddComponent<Image>();
img.rectTransform.position = Vector2.zero;

と、しても原点に生成されないときがあります。

UIの複数の解像度にも対応した相対的な位置は、"anchoredPosition"を使用します。

Image img = new GameObject("obj").AddComponent<Image>();
img.rectTransform.anchoredPosition = new Vector2(0,0);

Publicな変数がInspectorでも変更できてしまう

宣言した変数上に"[System.NonSerialized]"を書けばInspectorに表示されなくなります。

Editorで変更する仕様でない限り、書いておけば他人が見たときに外から読み取りたい旨がわかるようになります。

[System.NonSerialized]
Public int hoge = 0;

Privateな変数をInspectorに表示させたい

表示させたい変数の上に"[SerializeField]"を書く。

Editor上で値を書き換えたいときにPublicだと外から読み(書き)たいのか、Inspectorから指定したいのかわからないので、privateな変数でも大丈夫ならこちらの方法で書くといいでしょう。

[SerializeField]
private int hoge = 0;

フレームレートが落ちる(カクカクする)とキャラクターのスピードが遅くなる

Unity上でスクリプトを作成するとデフォルトでUpdate()が生成されてしまうため、そこに書きがちですが、Updateはフレームレート依存な関数なので、移動などの物理的な挙動に関してはFixedUpdate()に書くか、Update()に書く場合はTime.deltaTimeをかけるといいです。
参考までに

void Update()
{
  gameObject.transform.position += Vector3.forward * Time.deltaTime;
}

もしくは、

void FixedUpdate()
{
 gameObject.transform.position += Vector3.forward;
}

他のScriptから参照したい

UnityというかC#の話なうえ、ケースバイケースでその時によって変わりますが、使い分けてください。

当たり前に使うことですが、なぜか調べてもなかなか出てこない上にGameObject.Find()が目立っている気がしたのでいろいろな方法を載せておきます。

ManagerとしてSingletonにする

Enemyとか、Itemなど同じものが複数個生成される場合では使えませんが、GameManager等の一つしか生成されないスクリプトによく使う方法です。

hogeManager.cs
public int hoge = 100;

public static Instance;
void Awake()
{
 if(Instance == null) Instance = this;
}

void OnDisable()
{
 Instance = null;
}

とし、呼び出すほうでは、

void Start()
{
 Debug.Log(hogeManager.Instance.hoge); //100
}

とすると簡単に使用できます。Singletonの詳しい使い方や組み方、MonoBehaviourとのより良い共存方法などは調べると沢山出てきます。

そちらのほうが丁寧に分かりやすく解説されていると思いますので、各自で調べてみてください。

FindWithTag()等で保持しておく

参照したいScriptがついているGameObjectにTagをつけて、StartやAwakeで保持しておく方法。

GameObject.Find()でも大丈夫ですが、重たい処理な為、特に利用が制限される場合じゃなければFindWithTag()を利用するのが無難だと思います。

HogeScript hoge;

void Start()
{
 hoge = GameObject.FindWithTag("hoge").GetComponent<HogeScript>();
}

Inspectorで直接アタッチする

SerializeField等でInspectorに表示させ、ドラッグアンドドロップでアタッチする方法です。

直感的でわかりやすく手間のかからない方法ですが、プロジェクトファイルを移動した際にアタッチが外れることが多々あります。

接触したオブジェクトに送る

上記と違い、極端に限定的ですが、Enemyに当たったらダメージを与えるとか、Itemに触れたらインベントリに入れるなど、

接触した時に接触したもののスクリプトを呼びたい時に使う方法です。

void OnTriggerEnter(collider col)
{
 if(col.tag == "enemy")
 {
  col.GetComponent<enemy>().Damage();
 }
}

あとがき

もっといろいろ書きたいことがあった気がしますが、思い出せないのでその都度更新していく予定です。

それではよきUnityライフを!

参考文献

Unity - Manual

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

【Windows Forms】TabControl配下にあるタブ一欄の高さを取得する

最初に

少しニッチな話題ですが、TabControlを動的に作る際にTabの選択欄の高さが欲しいことがありました。
「タブストリップ」と言うらしいです。

タブストリップの高さを取得する情報が見つけられなかったのでこの記事を作成しました。
ベストな道かはいまいち判断できませんが、同じことを実装されたいと考えた方々の参考になれば幸いです。

用語の意味

タブ・・・TabControlの上部に表示されるタブページを表示するためのコントロール(TabPageのことではない)
タブストリップ・・・タブを選択する一覧のこと(詳細は下記)
タブページ・・・TabControlの下部に表示される選択したタブと対応付けられたページのこと(TabPageオブジェクトのこと)
TabControl・・・タブストリップとタブページを持ち合わせたControlオブジェクト

タブストリップとは?

次の画像に表示されているタブの一覧のことを指します。

tab.png
※タブの名称がバラバラなのは気にしないでください

赤線が指している高さはTabControl配下のタブページの数とTabControlのWidthなどに依存するので、多ければ行が増えタブストリップのHeightは高くなり、少なければ行が減りタブストリップのHeightは低くなるはずです。

そもそもTabの選択欄の高さが必要になった背景は?

GroupBoxの配下へ動的にTabControlを追加した際に、次の2点の実装を行いたかったのです。
- TabControlの全て(タブストリップ・タブページ含め)が表示されるようサイズを明示的に指定
- GroupBoxは子コントロール(TabControl)のサイズに合わせて大きくするようにしたかった

実装

別に難しいことを考える必要はありませんでした。
「タブの高さ」と「タブストリップの行数」さえ分かれば取得できるでしょう。

次のように実装しました。

TabPage tabPage = new TabPage();
TabControl tab = new TabControl();
//「タブの高さ」×「タブストリップの行数」+「タブページの高さ」でtab全体を表示するための高さを取得
tab.Height = tab.ItemSize.height * tab.RowCount + tabPage.Height;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Windows Forms】TabControl配下にあるタブ欄の高さを取得する

最初に

TabControlを動的に作る際に「配下にあるタブ欄」の高さが欲しいことがありました。「タブストリップ」と言うらしいです。

タブストリップの高さを取得する情報が見つけられなかったのでこの記事を作成しました。
ベストな道かはいまいち判断できませんが、同じことを実装されたいと考えた方々の参考になれば幸いです。

用語の意味

タブ・・・TabControlの上部に表示されるタブページを表示するためのコントロール(TabPageのことではない)
タブストリップ・・・タブを選択する一覧のこと(詳細は下記)
タブページ・・・TabControlの下部に表示される選択したタブと対応付けられたページのこと(TabPageオブジェクトのこと)
TabControl・・・タブストリップとタブページを持ち合わせたControlオブジェクト

タブストリップとは?

次の画像に表示されているタブの一覧のことを指します。

tab.png
※タブの名称がバラバラなのは気にしないでください

赤線が指している高さはTabControl配下のタブページの数とTabControlのWidthなどに依存するので、多ければ行が増えタブストリップのHeightは高くなり、少なければ行が減りタブストリップのHeightは低くなるはずです。

そもそもタブストリップの高さが必要になった背景は?

TabControlを親コントロールへ追加する際に、次の2点の実装を行いたかったことがきっかけです。

  • TabControlの全て(タブストリップ・タブページ含め)が表示されるようサイズを変更
  • 親コントロールは子コントロール(TabControl)のサイズを元にサイズを調整する

1点目の実装で、TabControlのサイズを決めるためにはタブストリップの高さが必要になりました。

実装

難しいことを考える必要はありませんでした。
「タブの高さ」と「タブストリップの行数」さえ分かれば取得できます。

次のように実装しました。

TabPage tabPage = new TabPage();
TabControl tab = new TabControl();
//「タブの高さ」×「タブストリップの行数」+「タブページの高さ」でtab全体を表示するための高さを取得
tab.Height = tab.ItemSize.height * tab.RowCount + tabPage.Height;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ASP.NET CoreをNginxで動かす場合に必要なコード(メモ)

ASP.NET Core 構築で必要なコードのメモ

Nginxなどのプロキシーを通して配信する場合
日本語を含むコードの場合

そのほか、現在コーディング中においてのメモ他

日本語対処用コード

日本語と言うよりUTF8による2byte以上の文字の場合にHTMLエンティティされる問題を解決するおまじない

        public void ConfigureServices(IServiceCollection services)
        {
            // UTF8文字コード設定
            services.Configure<Microsoft.Extensions.WebEncoders.WebEncoderOptions>(options =>
            {
                options.TextEncoderSettings = new System.Text.Encodings.Web.TextEncoderSettings(System.Text.Unicode.UnicodeRanges.All);
            });

            ... 以下略

プロキシー設定

プロキシーを通す場合のおまじない

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ... 以下略

            // リバースプロキシー設定用
            app.UseForwardedHeaders(new Microsoft.AspNetCore.Builder.ForwardedHeadersOptions
            {
                ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
            });

            ... 以下略

設定情報

設定情報系の読み込み用のおまじない(まだ意味の把握全容が出来ていない)

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;

... 以下略

        public Microsoft.Extensions.Configuration.IConfigurationRoot Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();

            ... 以下略

途中です。

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