47
Help us understand the problem. What are the problem?

posted at

updated at

【C#】C#で作成したDLLをC#で呼ぶ(静的/動的)

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

C#で作ったDLLを、C#で使いたい。

呼ばれる側C#(=DLL)

[VisualC#] > [Windowsデスクトップ]の中の[クラスライブラリ(.NET Framework)]を選択し、プロジェクトを作成する。
image.png

デフォルトで、下記のようなコードが生成される。

class1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class Class1
    {
    }
}

ここに、DLLで行いたい処理を記述する。
今回は、下記のようにした。

MyCsDllClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DllTestCs
{
    public class MyCsDllClass
    {
        public List<MyData> DataList = new List<MyData>();

        /// <summary>
        /// staticなメソッド。ただの足し算を行う。
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static int Add(int a, int b) => a + b;

        /// <summary>
        /// データリストに引数のデータを追加する。
        /// 追加後のデータリストの件数を返す。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public int AddMyData(MyData data)
        {
            if (data != null)
            {
                DataList.Add(data);
            }

            return DataList.Count;
        }

        /// <summary>
        /// 引数で指定したindexを持つデータがリスト内にあればそれを返す。
        /// 無ければnullを返す。
        /// </summary>
        /// <param name="serachIndex"></param>
        /// <returns></returns>
        public MyData DataSearch(int serachIndex) => DataList.FirstOrDefault(x => x.index == serachIndex);
    }

    /// <summary>
    /// お試しデータのクラス。
    /// </summary>
    public class MyData
    {
        public int index;
        public double data;
    }
}

呼ぶ側C#(=アプリ)

まず、呼び出したいアプリ側のプロジェクトの「参照」に、上で作成したDLLを追加する。

image.png

image.png

参照を追加したら、そのDLLに含まれるクラスやメソッドを使用し、コーディングを行う。今回は、下記のようにした。

Program.cs
using DllTestCs;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // C#のDLLを呼ぶ(プロジェクトの参照に、DLLを追加し、このファイルの上にusingを追加)
            int a = MyCsDllClass.Add(1, 2);
            var mcdc = new MyCsDllClass();
            mcdc.AddMyData(new MyData() { index = 1, data = 1.1 });
            mcdc.AddMyData(new MyData() { index = 2, data = 2.2 });
            mcdc.AddMyData(new MyData() { index = 3, data = 3.3 });
            var result = mcdc.DataSearch(2);
            var result2 = mcdc.DataSearch(5);
        }
    }
}

備考

  • C#は、DLLを作る時も呼ぶときも、C++よりもかなり簡単に作れて呼べる。(普通にクラスを作って、呼ぶ側で参照に追加するだけ)
  • C++で作成したDLLをC++で呼ぶときと同じで、C#でDLLを呼ぶときも「動的」に呼べるらしい。(未検証)必要に迫られていないので、そのうちやり方確認したい。

コード

動的呼び出し(19/04/05追記)

動的に呼び出すには、下記のようにする。

動的呼び出し側サンプル.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CSharpConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            var asm = Assembly.LoadFrom("CSharpDll.dll");       // アセンブリの読み込み
            var module = asm.GetModule("CSharpDll.dll");        // アセンブリからモジュールを取得
            var Person = module.GetType("CSharpDll.Person");    // 利用するクラス(or 構造体)を取得

            if (Person != null)
            {
                // CSharpDll.Personクラスをインスタンス化.
                // コンストラクタへ引数を渡すことも可能.
                dynamic p1 = Activator.CreateInstance(Person, "Aiueo", 29);    

                // dynamicで受けているので, 面倒なプロパティ取得やメソッド取得を省略できる.
                Console.WriteLine($"name= {p1.Name}");
                Console.WriteLine($"age= {p1.Age}");
                Console.WriteLine(p1.ToString());
            }

            Console.ReadKey();
        }
    }
}
dll側サンプル.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDll
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Person() : this("", 0) { }
        public Person(string name, int age) => (Name, Age) = (name, age);

        public override string ToString() => $"{Name} ({Age})";
    }
}

通常、動的な呼び出しは行わない。
使われるのは、プラグインを作る場合などにほとんど限られる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
47
Help us understand the problem. What are the problem?