2011-01-06 73 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做什么,所以我用你的方式取代我的代码,它的工作方式 - 所以这可能不会帮助你]