2010-03-05 7 views
6

Por el momento, intento crear un tipo de modelo en vb.net que se pueda usar para crear/obtener bases de datos de entrys.Método para "anular" miembros compartidos en clases secundarias

Creé un modelo de clase principal con una función compartida para buscar los conjuntos de datos, p. Model.find(). Ahora me gustaría crear clases que hereden la clase modelo principal, p. Ej. una separada para los usuarios: UserModel.find() => "SELECT * FROM users".

Lo que necesito ahora es encontrar una manera de decirle a la clase qué tabla debe usar. Pensé en una "tabla" de cadenas abstracta que es una constante en cada "modelo hijo", pero ¿cómo podría implementarse esto ya que no es posible anular los miembros compartidos?

¡Gracias de antemano!

Editar: Tal vez esto hará que sea un poco más claro lo que quiero decir:

Public Class Model 
Public Shared _controller As Controller 

Public Shared table As String 
Protected Shared tableFields As String() 
Shared reader As Npgsql.NpgsqlDataReader 

Public Shared Function find() 
    Dim a As ArrayList = New ArrayList 

    'Test if the tablefields are already known to the class, if not, get them 

    If tableFields Is Nothing Then 
     getTableFields() 
    End If 

    Dim query As String = "SELECT " + String.Join(", ", tableFields) + " FROM " + table 
    reader = _controller.executeReader(query) 
     While reader.Read 
      o = New Model 
      Dim v As New Hashtable 
      For Each field In tableFields 
       v(field) = reader(field) 
      Next 
      o.values = v 
      a.Add(o) 
     End While 
     reader.Close() 
     Return DirectCast(a.ToArray(GetType(Model)), Model()) 
End Function 

Public values As Hashtable 

Public Sub New() 
End Sub 

End Class 

Así que quiero un método compartido que encuentra todas las entradas de base de datos y devuelve una serie de ejemplos de su propio tipo, p.ej Modelo(). Es por eso que quería mantener el método find compartido y no vinculado a una instancia.

Respuesta

4

Creo que podría usar Generics.Aquí he pegado un ejemplo

Todas las clases en su dominio podían heredar de la clase de entidad

Public MustInherit Class Entity 

    '... 

End Class 

Su clase Modelo, con su método Encuentra

Public Class Model 

    Public Shared Sub Find(Of T As Entity)() 

     ' You could know the name of T to find the table 

     Dim tableName As String = GetType(T).Name 

     '... 

    End Sub 

End Class 

Una clase de su dominio, por ejemplo: Clase de usuario

Public Class User 
    Inherits Entity 

    ' ... 

End Class 

Y, por último, un ejemplo de cómo podría que una instancia del método Find

Model.Find(Of User)() 

'... 

No sé si esto es lo que quieres decir, ¿se encuentra este servicial?

0

Puede hacer que su clase principal sea abstracta y cada subclase tendrá que devolver su nombre de tabla "propia" a través de su propia implementación (por ejemplo, getTableName). De esta forma, solo tendrías que mantener tu lógica de método en la clase principal.

0

Es común usar el patrón de diseño de Singleton en tales casos: cree un método de instancia, anulado heredando clases. Cada clase heredada debe hacer que ese método de instancia devuelva un objeto Singleton relacionado con esa clase.

Esta es una manera de hacerlo:

MustInherit Class BaseClass 
    Public MustOverride Function getTableName() As String 
End Class 

Class Class1 
    Inherits BaseClass 
    Private Shared TableName As String = "myTable1" 
    Public Overrides Function getTableName() As String 
     Return TableName 
    End Function 
End Class 

Class Class2 
    Inherits BaseClass 
    Private Shared TableName As String = "myTable2" 
    Public Overrides Function getTableName() As String 
     Return TableName 
    End Function 
End Class 

EDIT: un enfoque completamente diferente. Usted puede tener la clase base porten algún diccionario, que relaciona los tipos de clases (o escribir los nombres) con la tabla correcta:

Class BaseClass 
    Private Shared myDictionary As New Collections.Generic.Dictionary(Of Type, String) 
    Friend Shared Sub RegisterType(ByVal childType As Type, ByVal tableName As String) 
     myDictionary.Add(childType, tableName) 
    End Sub 
    Public Shared Function getTableName(ByVal childType As Type) As String 
     Return myDictionary.Item(childType) 
    End Function 
End Class 
Class Class1 
    Shared Sub New() 
     BaseClass.RegisterType(GetType(Class1), "table1") 
    End Sub 
End Class 
Class Class2 
    Shared Sub New() 
     BaseClass.RegisterType(GetType(Class2), "table2") 
    End Sub 
End Class 
+0

Eso es lo que probé antes, el problema es que necesito el nombre de la tabla en el método compartido y no puedo declarar una función compartida pública como overridable/mustoverride. ¿O no entendí tu código? – stex

+0

La función getTableName no se comparte; es un método de instancia "normal", que debe ser reemplazado por subclases. Cada subclase que anula este método devuelve una variable privada compartida (o una constante a nivel de clase, si es posible). Cada instancia de Class1 devolverá el mismo TableName, a pesar de que getTableName es un método de instancia y no un método compartido. La idea es hacer que un método de instancia actúe como un método compartido cuando se desencadena (devuelve el mismo valor/referencia, sin importar el método de la instancia que se invoque), manteniendo los beneficios de la anulación en subclases. –

+0

Sí, lo entiendo. Pero no quiero crear una instancia de Class1, quiero que Class1 sepa sobre el nombre de la tabla sin crear un objeto. – stex

0

compartida (estática) objetos o miembros de objetos no puede ser heredada o overrided. La herencia es, por ejemplo, un objeto. Como no tiene que instanciar una clase estática, no puede heredar de ella. Lo mismo con los métodos. Un método estático no debe ser virtual (Anulable en VB) ya que define un método que realiza tareas sin instancia de la clase. Entonces esto imposibilita el uso de campos de instancia o propiedades dentro de un método estático (Shared in VB). Este es un mal diseño al intentarlo.

De hecho, todas las clases estáticas (Compartidas) deben marcarse como No Inferificables en VB y definir el constructor vacío predeterminado únicamente. Esta es una fuga de VB con respecto a los conceptos de OOP.

Cuestiones relacionadas