web-dev-qa-db-ja.com

実行時に.NETアセンブリを読み込み、名前のみを知っている型をインスタンス化できますか?

プロジェクトのアセンブリへの参照を追加せずに、DLL名とクラス名のみを持っている場合、実行時にオブジェクトをインスタンス化することは可能ですか?クラスはインターフェイスを実装しているため、クラスをインスタンス化したら、インターフェイスにキャストします。

アセンブリ名:

library.dll

タイプ名:

Company.Project.Classname


編集: DLLの絶対パスがないため、Assembly.LoadFileは機能しません。 DLLは、アプリケーションルートsystem32にあるか、GACにロードされている場合もあります。

171
MegaByte

はい。 Assembly.LoadFrom を使用してアセンブリをメモリにロードする必要があります。その後、 Activator.CreateInstance を使用して、希望するタイプのインスタンスを作成できます。リフレクションを使用して、最初にタイプを調べる必要があります。以下に簡単な例を示します。

Assembly assembly = Assembly.LoadFrom("MyNice.dll");

Type type = Assembly.GetType("MyType");

object instanceOfMyType = Activator.CreateInstance(type);

更新

アセンブリファイル名と型名がある場合は、 Activator.CreateInstance(assemblyName, typeName) を使用して、.NET型解決にそれを型に解決するように依頼できます。それをtry/catchでラップすると、失敗した場合に、検索されない可能性のある追加のアセンブリを具体的に保存できるディレクトリの検索を実行できます。これは、その時点で前述の方法を使用します。

215
Jeff Yates

さまざまなLoad*メソッドの制限を考慮してください。 MSDN docs ...から.

LoadFileはファイルをLoadFromコンテキストにロードせず、はLoadFromメソッドのようにロードパスを使用して依存関係を解決しません。

コンテキストの読み込みの詳細については、 LoadFrom のドキュメントをご覧ください。

34

Activator.CreateInstance 動作するはずです。

IFace object = (IFace)Activator.CreateInstance( "AssemblyName",
                                                "TypeName" )
                               .Unwrap();

注:型名は完全修飾型でなければなりません。

例:

var aray = (IList)Activator.CreateInstance("mscorlib","System.Collections.ArrayList").Unwrap();
aray.Add(10);

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}
18
tvanfosson

この質問といくつかの回答は非常に有用であることがわかりましたが、パスの問題があったため、この回答ではbinディレクトリパスを見つけてライブラリをロードする方法を説明しました。

最初の解決策:

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type T = Assembly.GetType("Company.Project.Classname");
Company.Project.Classname instance = (Company.Project.Classname) Activator.CreateInstance(T);

第二の解決策

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFile(assemblyPath);
(Company.Project.Classname) instance = (Company.Project.Classname) Assembly.CreateInstance("Company.Project.Classname");

次のようなインターフェイスに同じ原則を使用できます(クラスを作成しますが、インターフェイスにキャストします)。

(Company.Project.Interfacename) instance = (Company.Project.Interfacename) Assembly.CreateInstance("Company.Project.Classname");

この例はWebアプリケーション用ですが、デスクトップアプリケーションにも同様の方法を使用できます。たとえば、パスのみが異なる方法で解決されます。

Path.GetDirectoryName(Application.ExecutablePath)
6
Sofija

Framework v4.5以降では、Activator.CreateInstanceFrom()を使用して、アセンブリ内のクラスを簡単にインスタンス化できます。次の例は、それを使用する方法と、パラメーターを渡して戻り値を取得するメソッドを呼び出す方法を示しています。

    // Assuming moduleFileName contains full or valid relative path to Assembly    
    var moduleInstance = Activator.CreateInstanceFrom(moduleFileName, "MyNamespace.MyClass");
    MethodInfo mi = moduleInstance.Unwrap().GetType().GetMethod("MyMethod");
    // Assuming the method returns a boolean and accepts a single string parameter
    bool rc = Convert.ToBoolean(mi.Invoke(moduleInstance.Unwrap(), new object[] { "MyParamValue" } ));
3
afiorillo

それは簡単です。

MSDNの例:

public static void Main()
{
    // Use the file name to load the Assembly into the current
    // application domain.
    Assembly a = Assembly.Load("example");
    // Get the type to use.
    Type myType = a.GetType("Example");
    // Get the method to call.
    MethodInfo myMethod = myType.GetMethod("MethodA");
    // Create an instance.
    object obj = Activator.CreateInstance(myType);
    // Execute the method.
    myMethod.Invoke(obj, null);
}

ここに参照リンクがあります

https://msdn.Microsoft.com/en-us/library/25y1ya39.aspx

3
user3722131

はい。私が個人的に利用できるようにした例は今のところありません。後で見つけたら投稿します。基本的に、リフレクションを使用してアセンブリをロードし、必要なタイプをプルします。

それまでの間、このリンクから開始してください。

実行時にリフレクションを使用して参照されていないアセンブリを読み込む

2
Giovanni Galbo
((ISomeInterface)Activator.CreateInstance(Assembly.LoadFile("somePath").GetTypes()[0])).SomeInterfaceMethod();
2
abatishchev

この種の機能がプロジェクトにどの程度内在しているかに応じて、 MEF のようなものを検討することをお勧めします。

2
Kent Boogaart

* Assembly.Load **メソッドを使用してアセンブリをロードできます。 Activator.CreateInstanceを使用すると、必要なタイプの新しいインスタンスを作成できます。ロードするクラスの完全な型名を使用する必要があることに注意してください(たとえば、Namespace.SubNamespace.ClassName)。 TypeクラスのメソッドInvokeMemberを使用すると、そのタイプのメソッドを呼び出すことができます。

また、一度ロードされると、AppDomain全体もアンロードされるまでアセンブリをアンロードできないことを考慮してください(これは基本的にメモリリークです)。

2
Dario Solera
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");

Type type = Assembly.GetType("MyType");

dynamic instanceOfMyType = Activator.CreateInstance(type);

したがって、この方法では、methodinfoを取得してから呼び出すことなく、関数を使用できます。このようにinstanceOfMyType.MethodName();ただし、動的型はコンパイル時ではなく実行時に入力されるため、Intellisenseは使用できません。

2
David Mkheyan

はい、そうです。Assemblyクラスで静的なLoadメソッドを使用し、Loadの呼び出しから返されたAssemblyインスタンスでCreateInstanceメソッドを呼び出して呼び出します。

また、必要に応じて、Assemblyクラスの「Load」で始まる他の静的メソッドの1つを呼び出すことができます。

1
casperOne

この方法で次のことができます。

using System.Reflection;

Assembly MyDALL = Assembly.Load("DALL"); //DALL name of your Assembly
Type MyLoadClass = MyDALL.GetType("DALL.LoadClass"); // name of your class
 object  obj = Activator.CreateInstance(MyLoadClass);
0
Pankaj