1

好的,所以我正在尝试为数据访问对象创建一个不错的超类,它可以生成一个 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

4 回答 4

2

当您“通过”派生类调用静态方法时,编译器会解析该方法,因此 IL 实际上包含基类。例如:

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

public class Derived : Base {}

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

Main 中的调用实际上最终会在 IL 中编译为 Base.Foo() (至少在从 C# 编译时)。因此,您无法在执行时说出原始调用是什么。

这听起来确实像泛型是要走的路。

于 2009-01-19T17:26:18.510 回答
1

我认为大多数存储库模式使用接口而不是像这样的抽象类......

 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/

有什么理由不能使用接口吗?

于 2009-01-19T16:51:11.917 回答
1

好吧,假设您仍然想要一个答案:不。在静态方法中,您不在对象的上下文中。你不知道是谁给你打电话(没有构造 a StackTrace),即使你打电话了,你也不知道调用者是应该枚举其属性的对象。

如果它是一个实例方法,你可以调用GetType().

于 2009-01-19T16:52:34.990 回答
0

我只是按照您的建议工作(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'
于 2010-07-03T03:35:03.487 回答