开发者

.net dynamic loading

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.

Publ开发者_StackOverflow中文版ic 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?


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.


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]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜