2011-01-06 75 views
0

我已經看到了一些其他的迴應,他們談論的接口,但我敢肯定,你可以做到這一點的類和基類,但我不能這個工作。.net動態加載

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)返回到基類類型的行爲我越來越無效拋出異常。該類型應該是CharacterController,它被定義爲Behavior的子元素,所以爲什麼它不讓我進行該操作?我之前做過這樣的事情,但是我找不到我的代碼。我錯過了什麼?

+0

也許使用'DirectCast(Activator.CreateInstance(t),Behavior)' – IAbstract 2011-01-06 01:46:10

+0

是的,我試了兩次,它仍然沒有工作。 :/ – user441521 2011-01-06 01:54:54

+1

也許你應該檢查返回的對象的類型,看看它到底是什麼。 – cdhowie 2011-01-06 01:56:15

回答

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類型,然後派生出這種類型(兩級繼承),則此代碼將錯誤地跳過該類型。即使在繼承樹中的類型之間存在另一種類型,使用IsAssignableFrom方法可以快速簡便地確保一種類型實際上是從所需的特定類型(而不是任何共享相同名稱的類型)中派生出來的。針對t.IsAbstract的附加檢查還將確保您不會嘗試實例化基本插件類型的抽象子類型。

+0

很酷,我會用上面的。我不喜歡嵌套命名空間,但老實說,在這種情況下,它是每個DLL一個類,並給項目一個有意義的名稱,我只是創建該項目是什麼類。當然,這也是命名空間。我意識到我可以改變它,但我永遠不知道要改變它。它似乎讓我做Behavior.Behavior只是好嗎? – user441521 2011-01-06 02:05:32

+0

@ user441521:嗯,我認爲這是一個CIL級別的限制,但也許它只是C#中的限制。 – cdhowie 2011-01-06 02:06:28

+0

這很有趣。我把它放進去,它現在不通過if檢查!這可以解釋爲什麼它會給出錯誤,但現在仍然可以確定我錯過了什麼。 – user441521 2011-01-06 02:10:07

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) 

(如果我發現,我調用參數的構造函數)。

[我才意識到這可能是Activator.CreateInstance做什麼,所以我用你的方式取代我的代碼,它的工作方式 - 所以這可能不會幫助你]