Как получить объект Type подкласса в статической функции суперкласса в .net, используя отражение? - PullRequest
1 голос
/ 19 января 2009

Хорошо, поэтому я пытаюсь создать хороший суперкласс для объектов доступа к данным, который может сгенерировать запрос tsql для поиска всех открытых свойств строки подкласса. Я хочу использовать отражение, чтобы получить тип подкласса, а затем перебрать все свойства открытых строк в объекте, поскольку эти имена свойств совпадают с именами столбцов базы данных. Затем я могу использовать эти имена свойств для генерации запроса tsql.

[предостережение: эй, я скорее использую nhibernate, но я никак не могу убедить этих парней использовать это]

[Также я мог бы решить это с помощью дженериков, но я думаю, что дженерики их пугают, потому что они парни из VB.net (извините, если я вас обидел, VB.net выглядывает; ()]

Хорошо, базовый объект выглядит примерно так:

public abstract class RepositoryBase
{
   public static IList<RepositoryBase> Search()
   {
        //get all public properties of the inheriting subclass
        // I already have the rest of the search code
   }
}

Это вообще возможно или желательно?

Пока я печатал это, я как бы «прикрутил, я просто сделаю это с помощью дженериков».

Спасибо за чтение!

Ответы [ 4 ]

2 голосов
/ 19 января 2009

Когда вы вызываете статический метод «через» производный класс, компилятор разрешает метод так, что IL фактически содержит базовый класс. Например:

public class Base
{
    static void Foo() {}
}

public class Derived : Base {}

class Test
{
    static void Main()
    {
        Derived.Foo();
    }
}

Вызов в Main будет фактически скомпилирован как Base.Foo () в IL (как минимум при компиляции из C #). Таким образом, вы не можете сказать во время выполнения, каким был исходный вызов.

Звучит так, будто дженерики - это путь.

1 голос
/ 19 января 2009

Хорошо, если вы все еще хотите получить ответ: нет. В статическом методе вы не находитесь в контексте объекта. Вы не представляете, кто вам звонил (без построения StackTrace), и даже если вы это сделали, вы не знаете, что вызывающий объект - это объект, для которого должны быть перечислены свойства.

Если бы это был метод экземпляра, вы могли бы просто вызвать GetType().

1 голос
/ 19 января 2009

Я думаю, что большинство шаблонов хранилищ используют интерфейсы, а не абстрактные классы, подобные этой ...

 public class SqlRepository : IRepository {

        DB _db;

        public SqlRepository(DB dataContext) {
            //override the current context
            //with the one passed in
            _db = dataContext;

        } 

        public IQueryable<RepositoryBase> Search() {

           ...

Я не думаю, что когда-либо видел шаблон, написанный таким образом. Я полагаю, это возможно, но я не думаю, что вы сможете выполнить то, что, как вы думаете, вы пытаетесь достичь. Проверьте это ... http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/19a968ce-7d8b-4cf9-b0f0-292464f1e708/

Есть ли причина, по которой вы не можете использовать интерфейсы вместо этого?

0 голосов
/ 03 июля 2010

Я просто работаю (VB) в том, что вы предлагаете. Этот код работает (перевод с испанского, чтобы он мог содержать опечатки): Например, это можно использовать так:

Public Sub Main()
   'the SELEC method used below this line is written once and called from every table/class'
   Dim CustList As List(Of CUSTOMER) = CUSTOMER.SELEC("Name = 'Peter'", "Name DESC")
   Dim myOrders As List(Of ORDER) = CustList(0).Orders
   CustList(0).Name = "John"
End Sub


Public Interface ITables 'used solely to unify all the table types'
    '    ReadOnly Property PrimaryKey() As String is better to shadow it from SuperClass TableType'
End Interface

Public Class TableType(Of T As ITables)'this T is what you are looking for'
    Public PrimaryKey As String
    Public Shared Function SELEC(Optional ByVal sWhere As String = "", Optional ByVal sOrderBy As String = "") As List(Of T)
        'shared/static method to fill and return a typed List with the DB rows'
        'can be called using for example Type.SELEC()'
        Dim oConn As New OdbcConnection(My.Settings.ConnectionString)
        Dim oComm As OdbcCommand = oConn.CreateCommand
        oComm.CommandText = "SELECT * FROM " & GetType(T).Name
        If sWhere.Length > 0 Then oComm.CommandText &= " WHERE " & sWhere
        If sOrderBy.Length > 0 Then oComm.CommandText &= " ORDER BY " & sOrderBy
        Dim oListRet As New List(Of T)
        oConn.Open()
        Dim oDR As OdbcDataReader = oComm.ExecuteReader
        Dim oneRow As T
        Do While oDR.Read
            oneRow = Activator.CreateInstance(GetType(T))
            For i = 0 To oDR.FieldCount - 1
                Dim value = oDR.Item(i)
                If TypeOf value Is DBNull Then value = Activator.CreateInstance(oDR.GetFieldType(i)) ' default value'
                oneRow.GetType.GetProperty(oDR.GetName(i)).SetValue(oneRow, value, Nothing)
            Next
            oListRet.Add(oneRow)
        Loop
        oDR.Close()
        oConn.Close()
        oConn.Dispose()
        Return oListRet
    End Function

    Public Function UPDATE(Optional ByVal sWhere As String = "") As Integer
        'not shared but one for all tables'
        'working on this, almost finished'
    End Function
    Shared Function fnPropAttribute(ByVal oProp As PropertyInfo, ByVal sAttrName As String) As String
        'working on this. Returns for example the value of the attribute 'Category' of a field'
        Dim attributes As AttributeCollection = TypeDescriptor.GetProperties(oProp.DeclaringType)(oProp.Name).Attributes
        Dim myAttribute As CategoryAttribute = CType(attributes(GetType(need to know wth to put here)), CategoryAttribute)
        Return myAttribute.Category
    End Function
End Class 'TableType'


Public Class Tables
    Public Class CUSTOMER
        Inherits TableType(Of CUSTOMER)
        Implements ITables
        Public Shadows Const PrimaryKey As String = "idCust"

        'this returns the List(Of Orders) with my idCust'
        Public ReadOnly Property ORDERs() As List(Of ORDER)
            Get
                Return ORDER.SELEC("idCust = " & Me.idCust)
            End Get
        End Property

        Dim _idCust As Integer

        'this Attributes will be used in UPDATE, INSERT, etc'
        'Category 'Columns' is to distingish between DB fields and other possible properties'
        'Description is the ODBCType of the field'
        <Category("Columns"), Description("CHAR")> _
        Public Property idCust() As Integer
            Get
                Return _idCust
            End Get
            Set(ByVal value As Integer)
                _idCust = value
            End Set
        End Property

        Dim _Name As String
        <Category("Columns"), Description("CHAR")> _
        Public Property Name() As String
            Get
                Return _Name
            End Get
            Set(ByVal value As String)
                _Name = value
            End Set
        End Property
        'etc...'
    End Class 'Customer'
    Public Class ORDER
        Inherits TableType(Of ORDER)
        Implements ITables
        Public Shadows Const PrimaryKey As String = "idOrder"

        Dim _idOrder As Integer
        <Category("Columns"), Description("CHAR")> _
        Public Property idOrder() As Integer
            Get
                Return _idOrder
            End Get
            Set(ByVal value As Integer)
                _idOrder = value
            End Set
        End Property

        Dim _idCust As Integer
        <Category("Columns"), Description("CHAR")> _
        Public Property idCust() As Integer
            Get
                Return _idCust
            End Get
            Set(ByVal value As Integer)
                _idCust = value
            End Set
        End Property

        Dim _Artic As String
        <Category("Columns"), Description("CHAR")> _
        Public Property Artic() As String
            Get
                Return _Artic
            End Get
            Set(ByVal value As String)
                _Artic = value
            End Set
        End Property
        'etc...'
    End Class 'Order'
End Class 'Tables'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...