白猫のメモ帳

JavaとかC#とかJavaScriptとかHTMLとか機械学習とか。

リモートデスクトップはローカルのドライブをマウントできる

こんにちは。

気がつけば2月ももう半ば、今年1個目の記事です…ははは。
わたしはお仕事が忙しかったり、風邪を引いたり、インフルエンザに罹ったりしました。
体調管理大事!

リモートデスクトップは賢い

さて、Windowsを使っているとリモートデスクトップは割と日常的に使う機能です。
CUIの良さもわかるけど、やっぱりGUIいいよね。

で、RDPはとても賢いので、接続元(ローカルマシン)から接続先(リモートマシン)に対して、
ファイルのコピーとかもできちゃいます。(逆向きもできます)
なのですが、RDPのウィンドウの内外を往復しているとだんだんどっちの世界にいるかわからなくなってきます。

こんなときに便利なのがマウント機能です。

ドライブをマウントしよう

リモートデスクトップ接続のウィンドウで「ローカルリソース」というタブを選択すると、
「ローカルデバイスとリソース」という項目があり、その中に「詳細」設定ボタンがあります。

f:id:Shiro-Neko:20190216102041p:plain

f:id:Shiro-Neko:20190216102059p:plain

ドライブのところから「ローカルディスク」とかにチェックを入れて接続をすると…

f:id:Shiro-Neko:20190216102249p:plain

リモートマシンで「リダイレクトされたドライブとフォルダー」という項目があり、
ローカルマシンのドライブが参照できるようになりました。

f:id:Shiro-Neko:20190216102852p:plain

パスは「\\tsclient\C」みたいな感じになるみたいですね。

f:id:Shiro-Neko:20190216103058p:plain

ちなみに

ローカルディスクだけではなく、光学ドライブとかリムーバブルメディアとかもマウントすることができます。
光学ドライブがないマシンにソフトのインストールとかするときに便利かもしれませんね。
まぁ、最近はソフトのインストールとかはオンラインが主流な感じですが。

ジェネリックなコレクションのインスタンスをリフレクションで生成する

個人的なメモ。

たとえば、List<string>のインスタンスをリフレクションで生成したい場合、

var type = typeof(List<string>);
var instance = Activator.CreateInstance(type);

ってなるのだけれど、
任意のTypeインスタンスがあって、これのジェネリックなコレクションが生成したい場合、

var type = typeof(string);
var genericType= typeof(List<T>); // typeからT型が取りたいんだけど取れない
var instance = Activator.CreateInstance(genericType);

なんとなくこんなふうにしたいんだけど、このTはどっからくるんじゃい?ってなるわけで。
そんなときにはこうする。

var type = typeof(string);
var genericType= typeof(List<>).MakeGenericType(type);
var instanct = Activator.CreateInstance(genericType);

めもめも。

省略可能引数のあるメソッドをリフレクションで呼ぶ(C#)

こんばんは。

なんだか妙に暖かい日があったりしましたが、
すっかり冷え込んできて、気づけばもう12月。
今年も残すところあと少しですね。

今回はちょっとリフレクションについて。

そもそもリフレクションでメソッドってどうやって呼ぶ?

軽く確認を。
まずはこんなメソッドを呼んでみましょう。

public class Hoge
{
    public void Fuga(string piyo)
    {
        Debug.WriteLine("Fuga" + piyo);
    }
}

こんな感じ。

// メソッドを実行するインスタンス
var hoge = new Hoge();

// タイプを取得
var type = hoge.GetType();

// メソッドを取得
var method = type.GetMethod("Fuga");

// メソッドを実行
method.Invoke(hoge, new[] { "Piyo" });

タイプからメソッドをとってきて、
第一引数にメソッドを実行するインスタンス、第二引数にメソッドに渡す引数を設定します。
Invokeは戻り値を返しますが、今回はvoidなので取りません。

可変長引数の場合

ちょっと寄り道ですが、可変長引数の場合を軽く確認してみましょう。

public class Hoge
{
    public void Fuga(params string[] piyo)
    {
        Debug.WriteLine("Fuga" + string.Join("", piyo));
    }
}

こんな感じ。

~(略)~

// メソッドを実行
method.Invoke(hoge, new[] { new[] { "Piyo", "Piyo", "Piyo" } });

可変長引数は実体としては配列なので、配列としてパラメタを渡してあげればOKです。

省略可能引数の場合

で、本題。
こうして。

public class Hoge
{
    public void Fuga(string piyo = default(string))
    {
        Debug.WriteLine("Fuga" + piyo);
    }
}

こうすると、

~(略)~

// メソッドを実行
method.Invoke(hoge, new[] { "Piyo" });

普通に呼べますが、

~(略)~

// メソッドを実行
method.Invoke(hoge, null); // エラー
method.Invoke(hoge, new object[0]); // エラー

省略しようと思ってこんなふうにしてもエラーになってしまいます。
じゃあどうするかって言うと、

~(略)~

// メソッドを実行
method.Invoke(hoge, new[] { System.Type.Missing });

こんな感じに「System.Type.Missing」を指定してあげます。
せっかくなので拡張メソッドを作ってみましょう。

public static class Extensions
{
    public static object InvokeDefault(this MethodBase method, object obj, object[] parameters)
    {
        var len = method.GetParameters().Length;
        var param = (parameters ?? new object[0]).Concat(Enumerable.Repeat(System.Type.Missing, len)).ToArray();
        return method.Invoke(obj, param);
    }
}

省略可能パラメタは必須パラメタの後ろに書かなくてはならないので、
後ろに足りない分の「System.Type.Missing」を埋めてからInvokeしてあげる感じです。
パラメタを可変長引数にしてあげても良いかもしれないですね。

どうでもいいけどExtensionってtかsか大体いつもどっちが正解か自信がなくて調べてる気が…。