How to get an object of a subclass of Type in a static superclass function in .net using reflection?

So, I'm trying to make a good superclass for data access objects that can generate a tsql query to find all the properties of the public string of the subclass. I want to use reflection to get the type of the subclass, and then iterate over all the properties of the public row of the object, as these property names match the database column names. Then I can use these property names to generate a tsql query.

[caveat: hey, id is more likely to use nhibernate, but I just can't convince these guys to use this]

[I could also solve this with generics, but I think they find the pedigrees scary because they are guys from VB.net (sorry if I hurt you with VB.net peeps; ()]

So, the base object looks something like this:

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 } } 

Is this possible or advisable?

While I was typing this, I was like "screw it, I'll just do it with generics."

Thanks for reading!

+1
generics inheritance reflection repository
Jan 19 '09 at 16:35
source share
4 answers

When you call a static method "through" a derived class, the compiler solves this method, so IL actually contains the base class. For example:

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

A call in Main will actually compile as Base.Foo () in IL (at least when compiling with C #). Thus, at runtime you cannot specify what the initial call is.

It sounds like generics are the way to go.

+2
Jan 19 '09 at 17:26
source share

I think most repository templates use interfaces, not abstract classes like this ...

  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() { ... 

I do not think that I have ever seen a template written this way. I think this is possible, but I do not think that you can achieve what you think you are trying to achieve. Check it out ... http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/19a968ce-7d8b-4cf9-b0f0-292464f1e708/

Is there a reason you cannot use interfaces?

+1
Jan 19 '09 at 16:51
source share

Well, if you still want an answer: no. In a static method, you are not in the context of an object. You do not know who called you (without creating a StackTrace ), and even if you did, you do not know that the caller is an object for which properties should be listed.

If it was an instance method, you can just call GetType() .

+1
Jan 19 '09 at 16:52
source share

I just work (VB) in what you offer. This code works (translated from Spanish so that it can contain typos): For example, it can be used as follows:

 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' 
0
Jul 03 2018-10-10T00:
source share



All Articles