【发布时间】:2011-01-22 12:39:50
【问题描述】:
我正在尝试编写一些代码,允许我根据应用程序设置将 DLL 动态加载到我的应用程序中。这个想法是在应用程序设置中设置要访问的数据库,然后加载适当的 DLL 并将其分配给我的应用程序访问的接口实例。
这是我目前的代码:
Dim SQLDataSource As ICRDataLayer
Dim ass As Assembly = Assembly. _
LoadFrom("M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\SQLServer.dll")
Dim obj As Object = ass.CreateInstance(GetType(ICRDataLayer).ToString, True)
SQLDataSource = DirectCast(obj, ICRDataLayer)
MsgBox(SQLDataSource.ModuleName & vbNewLine & SQLDataSource.ModuleDescription)
我有我的接口 (ICRDataLayer),并且 SQLServer.dll 包含此接口的实现。我只想加载程序集并将其分配给 SQLDataSource 对象。
上面的代码不起作用。没有抛出异常,甚至没有出现 Msgbox。 我希望至少出现消息框,其中没有任何内容,但即使这样也不会发生!
有没有办法确定加载的程序集是否实现了特定的接口。我尝试了以下方法,但这似乎也没有任何作用!
For Each loadedType As Type In ass.GetTypes
If GetType(ICRDataLayer).IsAssignableFrom(loadedType) Then
Dim obj1 As Object = ass.CreateInstance(GetType(ICRDataLayer).ToString, True)
SQLDataSource = DirectCast(obj1, ICRDataLayer)
End If
Next
编辑:来自 Vlad 示例的新代码:
Module CRDataLayerFactory
Sub New()
End Sub
' class name is a contract,
' should be the same for all plugins
Private Function Create() As ICRDataLayer
Return New SQLServer()
End Function
End Module
上面是每个 DLL 中的模块,从 Vlad 的 C# 示例转换而来。
下面是我引入 DLL 的代码:
Dim SQLDataSource As ICRDataLayer
Dim ass As Assembly = Assembly. _
LoadFrom("M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\SQLServer.dll")
Dim factory As Object = ass.CreateInstance("CRDataLayerFactory", True)
Dim t As Type = factory.GetType
Dim method As MethodInfo = t.GetMethod("Create")
Dim obj As Object = method.Invoke(factory, Nothing)
SQLDataSource = DirectCast(obj, ICRDataLayer)
编辑:基于 Paul Kohler 的代码实现
Dim file As String
For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
Dim assemblyType As System.Type
For Each assemblyType In Assembly.LoadFrom(file).GetTypes
Dim s As System.Type() = assemblyType.GetInterfaces
For Each ty As System.Type In s
If ty.Name.Contains("ICRDataLayer") Then
MsgBox(ty.Name)
plugin = DirectCast(Activator.CreateInstance(assemblyType), ICRDataLayer)
MessageBox.Show(plugin.ModuleName)
End If
Next
我收到以下代码错误:
无法将“SQLServer.CRDataSource.SQLServer”类型的对象转换为“DynamicAssemblyLoading.ICRDataLayer”类型。
实际的 DLL 位于与我的实现代码相同的解决方案中名为 SQLServer 的不同项目中。 CRDataSource 是一个命名空间,而 SQLServer 是 DLL 的实际类名。 SQLServer 类实现了 ICRDataLayer,所以我不明白为什么它不能转换它。 这里的命名重要吗,我没想到会这样。
最终工作代码
PluginUtility 的内容:
enter code here Public Shared Function GetInstances1(Of Type)(ByVal baseDir As String, ByVal searchPattern As String) As System.Type()
Dim tmpInstances As New List(Of Type)
Try
Dim file As String
For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
Dim assemblyType As System.Type
For Each assemblyType In Assembly.LoadFrom(file).GetTypes
Dim s As System.Type() = assemblyType.GetInterfaces
Return s.ToArray()
Next
Next
Catch exp As TargetInvocationException
If (Not exp.InnerException Is Nothing) Then
Throw exp.InnerException
End If
End Try
End Function
加载 DLL 的代码:
enter code here
Dim basedir As String = "M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\"
Dim searchPattern As String = "*SQL*.dll"
Dim plugin As CRDataLayer.ICRDataLayer
Try
Dim file As String
For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
Dim assemblyType As System.Type
For Each assemblyType In Assembly.LoadFrom(file).GetExportedTypes
If assemblyType.GetInterface("CRDataLayer.ICRDataLayer") IsNot Nothing Then
plugin = DirectCast(Activator.CreateInstance(assemblyType), CRDataLayer.ICRDataLayer)
MessageBox.Show(plugin.ModuleDescription)
End If
Next
Next
Catch exp As TargetInvocationException
If (Not exp.InnerException Is Nothing) Then
Throw exp.InnerException
End If
Catch ex As Exception
MsgBox(ex.Message)
Clipboard.SetText(ex.Message)
End Try
【问题讨论】:
-
不要使用
ty.Name.Contains("ICRDataLayer")- 检查它是否使用assemblyType.GetInterface("your namespace etc.ICRDataLayer")“实现了类型”(参见http://msdn.microsoft.com/en-us/library/tcctb9t8.aspx)如果当前类型没有实现它,会给你Nothing。此外,异常似乎表明接口未实现,您是否为此使用共享 DLL - 它必须是同一个。 PK -
再次检查下面的解决方案...
-
有效!我最终使用了您的代码 Paul,它完全按照我的需要工作。对于将来可能遇到此线程的任何人,我会将我的最终代码添加到原始帖子中,因此希望他们可以比我更容易地让它工作。谢谢大家的帮助
标签: vb.net reflection dll assemblies