.net动态加载

发布于 2024-10-10 17:37:53 字数 2165 浏览 2 评论 0原文

我已经看到了一些关于此的其他回复,他们谈论了接口,但我很确定你可以使用类和基类来做到这一点,但我不能这样做。

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

End Class

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

End Class

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) 返回的任何内容转换为 Behaviour 类型的基类时,我收到无效的强制转换异常。该类型应该是CharacterController,它被定义为Behaviour的子级,那么为什么它不让我强制转换呢?我以前做过类似的事情,但找不到我的代码。我缺少什么?

I've seen some other responses about this and they talk about interfaces but I'm pretty sure you can do this with classes and base classes but I can't this to work.

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

End Class

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

End Class

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

When it tries to convert whatever Activator.CreateInstance(t) returns to the base class of type Behavior I'm getting invalid cast exception. That type should be of CharacterController which is defined as a child of Behavior so why wouldn't it let me cast that? I've done something like this before but I can't find my code. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

百变从容 2024-10-17 17:37:53

这可能不是你问题的答案(它也可能解决你的异常——谁知道呢),但这是需要指出的。这些行:

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”的随机类型并从另一种类型派生它,您的代码将认为它是一个插件。此外,如果有人派生您的行为类型,然后派生该类型(两级继承),则此代码将错误地跳过该类型。使用 IsAssignableFrom 方法是一种快速而简单的方法,可以确保一种类型确实派生自您想要的特定类型(而不是共享相同名称的任何类型),即使存在另一种类型继承树中的类型之间。针对 t.IsAbstract 的额外检查还将确保您不会尝试实例化基本插件类型的抽象子类型。

This may not be an answer to your question (it also might resolve your exception -- who knows), but it is something that needs to be pointed out. These lines:

If t.IsPublic Then
    If t.BaseType.Name = "Behavior" Then

Should really be changed to one conditional like this one:

If t.IsPublic AndAlso (Not t.IsAbstract) AndAlso _
    GetType(Behavior.Behavior).IsAssignableFrom(t) Then

Otherwise, if somebody defines a random type called "Behavior" in their own assembly and derives it from another type, your code will think it is a plugin. Additionally, if someone derives your Behavior type and then derives that type (two levels of inheritance) this code will incorrectly skip over that type. Using the IsAssignableFrom method is a quick and easy way to ensure that one type does actually derive from the specific type you want (instead of any type that shares the same name), even if there is another type in between your types in the inheritance tree. The additional check against t.IsAbstract will also ensure that you don't try to instantiate an abstract subtype of your base plugin type.

绮烟 2024-10-17 17:37:53

这对我有用:(

             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 所做的,所以我用你的代码替换了我的代码,它按照你的方式工作——所以这可能对你没有帮助]

This works for me:

             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)

(If I find t, I invoke the parameterless constructor.)

[I just realized this is probably what Activator.CreateInstance does, so I replaced my code with yours and it worked your way -- so this probably won't help you]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文