我已经看到了其他一些关于这个问题的回答,他们讨论了接口,但我很确定你可以用类和基类做到这一点,但我不能这样做。
Public Class Behavior
Private _name As String
Public ReadOnly Property Name As String
Get
Return _name
End Get
End Property
Public Property EditorUpdate As Boolean
Public Sub New(ByVal name As String)
_name = name
EditorUpdate = False
End Sub
Public Overridable Sub Update()
End Sub
' runs right away in editor mode. also runs when in stand alone game mode right away
Public Overridable Sub Start()
End Sub
' runs after game mode is done and right before back in editor mode
Public Overridable Sub Finish()
End Sub
' runs right when put into game mode
Public Overridable Sub Initialize()
End Sub
' runs when the game is complete in stand alone mode to clean up
Public Overridable Sub Destroy()
End Sub
结束班
Public Class CharacterController
Inherits Behavior.Behavior
Public Sub New()
MyBase.New("Character Controller")
End Sub
Public Overrides Sub Update()
' TODO: call UpdateController()
' THINK: how can UpdateController() get the controller entity it's attached to?
' Behaviors need a way to get the entity they are attached to. Have that set when it's assigned in the ctor?
End Sub
结束班
Dim plugins() As String
Dim asm As Assembly
plugins = Directory.GetFileSystemEntries(Path.Combine(Application.StartupPath, "Plugins"), "*.dll")
For i As Integer = 0 To plugins.Length - 1
asm = Assembly.LoadFrom(plugins(i))
For Each t As Type In asm.GetTypes
If t.IsPublic Then
If t.BaseType.Name = "Behavior" Then
behaviorTypes.Add(t.Name, t)
Dim b As Behavior.Behavior
b = CType(Activator.CreateInstance(t), Behavior.Behavior)
'Dim o As Object = Activator.CreateInstance(t)
End If
End If
Next
Next
当它试图转换任何Activator.CreateInstance(t)返回到类型为Behavior的基类时,我得到了无效的强制转换异常。那个类型应该是CharacterController,它被定义为一个行为的子项,所以为什么不让它转换它呢?我之前做过类似的事情,但是找不到我的代码。我错过了什么?
答案 0 :(得分:1)
这可能不是你问题的答案(它也可能解决你的例外 - 谁知道),但这是需要指出的。这些行:
If t.IsPublic Then
If t.BaseType.Name = "Behavior" Then
应该真的改成一个像这样的条件:
If t.IsPublic AndAlso (Not t.IsAbstract) AndAlso _
GetType(Behavior.Behavior).IsAssignableFrom(t) Then
否则,如果有人在自己的程序集中定义一个名为“Behavior”的随机类型并从另一个类型派生它,那么你的代码会认为它是一个插件。此外,如果某人派生您的Behavior
类型然后派生该类型(两个继承级别),则此代码将错误地跳过该类型。使用IsAssignableFrom
方法是一种快速简便的方法,可确保一种类型实际上从您想要的特定类型(而不是任何共享相同名称的类型)派生,即使您的类型之间存在其他类型在继承树中。对t.IsAbstract
的附加检查还将确保您不会尝试实例化基本插件类型的抽象子类型。
答案 1 :(得分:0)
这对我有用:
Dim ctor As Reflection.ConstructorInfo = _
t.GetConstructor(New System.Type() {})
Dim o As Object = ctor.Invoke(New Object() {})
Dim plugin As Plugin = TryCast(o, Plugin)
(如果我找到 t ,我会调用无参数构造函数。)
[我刚刚意识到这可能就是Activator.CreateInstance所做的,所以我用你的代码替换了我的代码并且它按照你的方式工作 - 所以这可能对你不起帮助]