views:

218

answers:

4

hi guys,

I am stuck with a problem about generic classes. I am confused how I call the constructor with parameters.

My interface:

Public Interface IDBObject
    Sub [Get](ByRef DataRow As DataRow)
    Property UIN() As Integer
End Interface

My Child Class:

Public Class User
    Implements IDBObject

    Public Sub [Get](ByRef DataRow As System.Data.DataRow) Implements IDBObject.Get

    End Sub

    Public Property UIN() As Integer Implements IDBObject.UIN
        Get

        End Get
        Set(ByVal value As Integer)

        End Set
    End Property
End Class

My Next Class:

Public Class Users
    Inherits DBLayer(Of User)

#Region " Standard Methods "

#End Region
End Class

My DBObject Class:

Public Class DBLayer(Of DBObject As {New, IDBObject})

    Public Shared Function GetData() As List(Of DBObject)
        Dim QueryString As String = "SELECT * ***;"
        Dim Dataset As DataSet = New DataSet()
        Dim DataList As List(Of DBObject) = New List(Of DBObject)

        Try
            Dataset = Query(QueryString)
            For Each DataRow As DataRow In Dataset.Tables(0).Rows
                **DataList.Add(New DBObject(DataRow))**
            Next
        Catch ex As Exception
            DataList = Nothing
        End Try
        Return DataList
    End Function
End Class

I get error in the starred area of the DBLayer Object.

What might be the possible reason? what can I do to fix it?

I even want to add New(byval someval as datatype) in IDBObject interface for overloading construction. but it also gives an error? how can i do it?

Adding

Sub New(ByVal DataRow As DataRow) in IDBObject producess following error 'Sub New' cannot be declared in an interface.

Error Produced in DBLayer Object line: DataList.Add(New DBObject(DataRow)) Msg: Arguments cannot be passed to a 'New' used on a type parameter.

A: 

Its not as simple as it being confused about what you are referring to? You've got the line "For Each DataRow As DataRow" which seems like a recipe for confusion and it may be that when you are referring to DataRow in your constructor it isn't using your loop variable but instead the datatype "DataRow". Even if that's not the problem you probably want to change your loop variable to something less ambiguous.

What is the actual error that you get?

Also for the last part of adding extra constructors what error do you get? If you are adding somethign to the interface are you adding the extra constructor to everythign that implements the interface?

Chris
Its not the loop error... I have added the error that is being produced
KoolKabin
A: 

for the constructor, that is because you can't define a constructor in an interface.

EDIT:

I see what you are trying to do now. you want to create a new instance of the generic type that your DBLayer is defined with. Your problem is going to be that you can't specify that your implementations of the interface need to have a particular constructor. You might be better having a method on your interface which accepts a DataRow and uses this to initialise the IDBObject, then you could create an instance of the type DBObject and then call the method which accepts the DataRow with which to intialize your instance.

Or you could require that your DBLayer class takes a factory class that can produce an object of type DBObject given a DataRow and you could call this method of the factory in place of calling

        For Each rowAs DataRow In Dataset.Tables(0).Rows
            //DataList.Add(New DBObject(row))
            DataList.Add(m_factory.CreateObject(row));
        Next

EDIT 2:

the easiest approach will be to extend your interface to allow you to set the DataRow and call the method in the loop:

        For Each row As DataRow In Dataset.Tables(0).Rows
            //DataList.Add(New DBObject(row))
            Dim newElement As IDBObject = CType(Activator.CreateInstance(GetType(DBObject)), IDBObject)
            //you'll need to add this SetDataRow method the the IDBObject interface
            newElement.SetDataRow(row)
            DataList.Add(newElement)
        Next
Sam Holder
so what can be done if i want something like to do DataList.Add(New DBObject(DataRow))Choosing different names isn't also solving that problem
KoolKabin
confused about m)factory or the class factory... i am not too much high level programmer... need some more basic concept... can you plz elaborate it
KoolKabin
edited my answer to elaborate
Sam Holder
tried as u said but it still says some error like: "Option Strict On disallows implicit conversions from 'IDBObject' to 'DBObject'". I have added a new sub in IDBObject for setDataRow(byval DataRow as DataRow)
KoolKabin
Try using `CType` instead of `DirectCast`
Sam Holder
or turn option strict off at the top of your code to see if it works. My VB is not that great, sorry.
Sam Holder
I can turn off option strict but i want it to be legally... without turning off so that unknown error doesn't occurs in runtime. anyway thnx for help sam
KoolKabin
did you try using `CType` instead of `DirectCast`?
Sam Holder
I tried using both.... now i am using the alternate way u suggested but just wanna know if it can be done from 1st method too also or not?
KoolKabin
do you mean you are using it with option strict turned off?
Sam Holder
I tried it with turn off worked but now i am using it with option strict turned on
KoolKabin
+1  A: 

The problem is with the New constraint. It only promises a parameter-less constructor, the compiler cannot deduce that the DbObject type parameter may have a constructor that takes a DataRow as an argument.

You could perhaps extend the IDbObject interface with a property that gets/sets a DataRow. A class factory would be helpful.

Hans Passant
A: 

What if you use an abstract class instead of the interface IDBObject? You should then inherit instead of implement. The abstract class could define the needed constructor.

Bert Heesbeen
can the abstract class be used while we do generics... any posting or code example?
KoolKabin
Instead of the interface you can use an abstract class (in Vb.Net the keyword is MustInherit). Defining your generic class, you only constraint the type to base types. Here the interface is the same as an abstract class.
Bert Heesbeen
whilst this idea is ok, there is no guarantee that the implementing class will contain the constructor you want, it might add extra parameters to the constructor, so you will not be able to call the constructor with the DataRow with certainty that it will not fail. The only thing you can guarantee is that with the `New` constraint on the type that the default constructor will exist.
Sam Holder