런타임에 .NET 어셈블리를로드하고 이름 만 알고있는 유형을 인스턴스화 할 수 있습니까?


178

프로젝트의 어셈블리에 대한 참조를 추가하지 않고 DLL 이름과 클래스 이름 만 가지고 있으면 런타임에 객체를 인스턴스화 할 수 있습니까? 클래스는 인터페이스를 구현하므로 클래스를 인스턴스화하면 인터페이스로 캐스트합니다.

어셈블리 이름 :

library.dll

유형 이름 :

Company.Project.Classname


편집 : DLL의 절대 경로 Assembly.LoadFile가 없으므로 작동하지 않습니다. DLL은 응용 프로그램 루트, system32에 있거나 GAC에로드되어있을 수도 있습니다.

답변:


221

예. 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로이를 랩핑하여 실패한 경우 검색하지 않을 수있는 추가 어셈블리를 구체적으로 저장할 수있는 디렉토리 검색을 수행 할 수 있습니다. 이 시점에서 앞의 방법을 사용합니다.


2
dll의 절대 경로가 없으므로 assemlby.LoadFile 요법입니다. 다른 아이디어가 작동하지 않습니까?
MegaByte

@rp 항상 도와 드리겠습니다 (그렇게 말하는 말 만 해!)
제프 예이츠

2
@MegaByte : LoadFrom이 LoadFile과 다릅니다. 종속성을 해결하고 알려진 경로 (GAC, exe 디렉터리 등)에서 DLL 이름을 확인해야합니다. 자세한 내용은 MSDN을 참조하십시오.
Jeff Yates

1
한 가지 더 ... (다시) 음, 유형 이름으로 "MyType"을 사용할 수 없으며 NAMESPACE가 와야합니다. 그래서 이것은 더 정확할 것입니다 :Type type = assembly.GetType("MyNamespace"+"."+"MyType");
Cipi

1
@Cipi : 기술적으로 유형은 전체 네임 스페이스 이름입니다 (네임 스페이스 개념은 언어 편의성). CLR 내에 네임 스페이스가없는 유형을 가질 수 있습니다-지나치게 단순화 된 예를 제공했습니다.
Jeff Yates

36

다른 Load*방법 의 한계를 고려하십시오 . 로부터 MSDN의 문서 ...

LoadFile은 LoadFrom 메소드로 파일을로드 하지 않으며 LoadFrom 메소드와 같이로드 경로를 사용하여 종속성분석 하지 않습니다.

컨텍스트로드에 대한 자세한 내용은 LoadFrom문서를 참조하십시오.


19

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);
}

1
이것에 대한 참고 사항 : TypeName정규화되어야합니다. : 내가 좋아하는이 전화를했다 Activator.CreateInstance("MyAssembly","MyAssembly.TypeName") 가 다시 표시 그리고 그 ObjectHandle. 인터페이스로 들어가려면해야 할 일ObjectHandle.UnWrap()
Anthony Sottile

7

이 질문과 일부 답변이 매우 유용하다는 것을 알았지 만 경로 문제가 있었 으므로이 답변은 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");

이 예는 웹 응용 프로그램을위한 것이지만 데스크톱 응용 프로그램에는 비슷한 것을 사용할 수 있습니다. 예를 들어 경로 만 다른 방식으로 해결됩니다.

Path.GetDirectoryName(Application.ExecutablePath)

5

그것은 간단합니다.

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


동적 코드 로딩을 ​​지원하는 끔찍한 방법입니다. MS는 항상 우리에게 너무 많은 세부 사항을 강요하는 것을 좋아했습니다.
Clearer

3

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" } ));


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

2

* Assembly.Load ** 메서드를 사용하여 어셈블리를로드 할 수 있습니다. Activator.CreateInstance 를 사용하여 원하는 유형의 새 인스턴스를 만들 수 있습니다. 로드하려는 클래스의 전체 유형 이름 (예 : Namespace.SubNamespace.ClassName ) 을 사용해야합니다 . 메소드를 사용하여 InvokeMember에유형 클래스 당신은 유형의 메소드를 호출 할 수 있습니다.

또한 한 번로드되면 전체 AppDomain이 언로드 될 때까지 (기본적으로 메모리 누수) 어셈블리를 언로드 할 수 없다는 점을 고려하십시오.


2

이러한 종류의 기능이 프로젝트에 얼마나 고유한지에 따라 MEF 와 같은 것을 고려 하여 구성 요소를로드하고 묶을 수 있습니다.


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

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

dynamic instanceOfMyType = Activator.CreateInstance(type);

따라서이 방법으로 methodinfo를 가져 와서 호출하지 않고 함수를 사용할 수 있습니다.이 instanceOfMyType.MethodName (); 그러나 동적 유형은 컴파일 타임이 아닌 런타임에 입력되므로 Intellisense를 사용할 수 없습니다.


1

예. Assembly 클래스에서 정적 Load 메서드를 사용한 다음 Load 호출에서 반환 된 Assembly 인스턴스에서 CreateInstance 메서드를 호출합니다.

또한 필요에 따라 Assembly 클래스에서 "로드"로 시작하는 다른 정적 메소드 중 하나를 호출 할 수 있습니다.


0

이런 식으로이 작업을 수행 할 수 있습니다.

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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.