CreateInstance () - 내가이 일을 제대로하고 있습니까?
-
09-09-2019 - |
문제
.NET으로 플러그인 시스템을 구성하려고 노력하고 있으며 올바르게하고 있는지 확실하지 않습니다. 시스템의 기초는 특정 디렉토리 ({apppath}/plugins/)가 사전 컴파일 된 DLL을 갖게되며, 특정 기본 클래스를 상속하는 경우 각 클래스에 대해 각 클래스에 대해 각 클래스를 살펴보고 싶다는 것입니다. (이것은 또 다른 DLL에 정의되어 있지만 나중에 나중에 들어가겠습니다) 그런 다음 인스턴스를 작성하고 해당 인스턴스에서 특정 함수를 호출합니다.
Public Sub ScanPluginsInDirectory(ByVal Directory As String)
Dim Plugins As New IO.DirectoryInfo(Directory)
Dim Files As IO.FileInfo() = Plugins.GetFiles("*.dll")
Dim CryptType As Type = GetType(CryptPluginBase)
Dim PluginsData as List(Of LoadedPluginsInfo)
For Each DllFile As IO.FileInfo In Files
Try
Dim thisAsm As Assembly = Assembly.LoadFrom(DllFile.FullName)
Dim ClassDefs = thisAsm.GetTypes().Where(Function(type) CryptType.IsAssignableFrom(type))
For Each ClassDef As Type In ClassDefs
Dim A As Object
A = ClassDef.Assembly.CreateInstance(ClassDef.Name)
PluginsData.Add(New LoadedPluginsInfo(A.Plugin(), False))
Next
Catch ex As Exception
Continue For
End Try
Next
End Sub
내가 가진 구체적인 문제는 이것이 이것이 올바른 방법인지 확실하지 않다는 것입니다. 내가 생각할 수 있다면 내가 일하려고하는 방법이 A.Plugin()
실제로 존재하고 여기에 언급 된 구조와 클래스는 버그가 없습니까? 도움을주기 위해 더 많은 코드가 필요한 사람이라면 게시 할 수 있습니다.
해결책
전반적으로 전략이 작동해야합니다. Assembly.Loadfrom 통화는 대상 어셈블리를 프로세스에로드합니다. 거기에서 유형 검사를 수행하고 이러한 유형의 인스턴스를 만들 수 있습니다.
인스턴스를 만드는 가장 쉽고 신뢰할 수있는 방법은 Activator.createInstance 메소드를 사용하는 것입니다.
For Each def As Type in ClassDefs
Dim inst = Activator.CreateInstance(def)
PluginsData.Add(new LoadedPluginsInfo(inst.Plugin(), False))
Next
목표에 따라 또 다른 제안은 시도/캐치 블록을 루프 대신 루프로 옮기는 것입니다. 루프 외부에 Try/Catch 블록이 있으면 어셈블리에 주어진 유형이 있으면 오류가 있으면 해당 어셈블리에서 모든 유형을 폐기합니다. 내부로 이동하면 기대대로 작동하지 않는 유형 만 폐기 할 수 있습니다 .D 현재 동작은 의도 일 수 있습니다.
다른 팁
이것은 효과가 있어야합니다. 나는 이전에 일부 프로젝트에서 이런 종류의 것을 사용해 왔습니다. 나는 구체적으로 생성자를 찾고 그것을 호출했지만 그 외에는 같은 생각이었습니다.
그러나 당신은보고 싶을 수도 있습니다 Mef, 플러그인 아키텍처를 위해 많은 것을 처리합니다 (릴리스 버전을 조금 기다릴 의향이 있다면 여전히 CTP입니다).