I use jQuery ajax calls to ASP.Net web services (ASMX files) to update the web page data.
I have the database storing code seperate from the domain object class code (in the example code below, there is an Animal class and an AnimalRepository class). I'm implememting a convention that all similar domain object repository classes will have a Store method .
I would like to create a web service that can cater for calling the Store method for any one of these repository classes. To get this to work, in the below code sample, the List(Of Animal) parameter would need to be a generic type.
I tried a List(Of Object), but the Store command errors on not able to convert types. I don't think I can cast the List(Of Object) to the right type, as it's not known until runtime.
<WebMethod(True)> _
Public Sub StoreAnimals(ByVal _animals As List(Of Animal), ByVal _type As String)
Dim classType As Type = Type.GetType(_type & "Repository, MyCompany.Assembly")
Dim instanceOfClass = Activator.CreateInstance(classType)
Dim method As MethodInfo = classType.GetMethod("Store")
method.Invoke(instanceOfClass, New Object() {_animals})
End Sub
Ideally, I would like:
<WebMethod(True)> _
Public Sub StoreData(Of T)(ByVal _data As List(Of T), ByVal _type As String)
Dim classType As Type = Type.GetType(_type & "Repository, MyCompany.Assembly")
Dim instanceOfClass = Activator.CreateInstance(classType)
Dim method As MethodInfo = classType.GetMethod("Store")
method.Invoke(instanceOfClass, New Object() {_data})
End Sub
There's no room for generics in the webservice method definition, but is there a trick to achieve the same end result.
Otherwise, I'm going to be creating lots of these Store* webservices that only differ on the first parameter.
Generics have no meaning in the web services world.
You can't come anywhere close to this with ASMX. With WCF, you might be able to do something, but you can't use an open generic type in an operation contract.
If you know what type of object you expect you could serialize the List(of Animal) to byte array and the deserialize the object from the byte array instead.
I made a small sample, in VB.NET though but I think you can translate it. I created a class which both the web service and the client shares.
Client code
Imports System.Xml.Serialization
Imports SharedLibrary
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim client As New ServiceReference1.WebServiceSoapClient
Dim a As New Animal
a.Name = "Pooh"
MessageBox.Show(client.SendObject(XmlSerialize(a), ServiceReference1.ObjectT.Animal))
Dim v As New Vehicle
v.Name = "Volvo"
MessageBox.Show(client.SendObject(XmlSerialize(v), ServiceReference1.ObjectT.Vehicle))
End Sub
Public Shared Function XmlSerialize(ByVal serializableObject As Object) As Byte()
Dim serializer As XmlSerializer = New XmlSerializer(serializableObject.GetType())
Dim aMemStr As New System.IO.MemoryStream
Dim writer As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(aMemStr)
serializer.Serialize(writer, serializableObject)
writer.Close()
aMemStr.Close()
Return aMemStr.ToArray()
End Function
Shared library
Public Class ObjectTypes
Public Enum ObjectT
Animal
Vehicle
End Enum
End Class
Public Class Animal
Private strName As String
Public Property Name As String
Get
Return strName
End Get
Set(value As String)
strName = value
End Set
End Property
End Class
Public Class Vehicle
Private strName As String
Public Property Name As String
Get
Return strName
End Get
Set(value As String)
strName = value
End Set
End Property
End Class
Web service
<WebMethod()> _
Public Function SendObject(bytObject As Byte(), objType As SharedLibrary.ObjectTypes.ObjectT) As String
Try
Select Case objType
Case ObjectTypes.ObjectT.Animal
Dim myAnimal As Animal = XmlDeSerialize(bytObject, GetType(Animal))
Return "I received an animal with name: " & myAnimal.Name
Case ObjectTypes.ObjectT.Vehicle
Dim myVehicle As Vehicle = XmlDeSerialize(bytObject, GetType(Vehicle))
Return "I received a vehicle with name: " & myVehicle.Name
End Select
Catch ex As Exception
Return "Something went wrong: " & ex.Message
End Try
Return "I did not receive anything :("
End Function
Public Shared Function XmlDeSerialize(ByVal xmlbytearr As Byte(), ByVal objectType As Type) As Object
Dim serializer As XmlSerializer = New XmlSerializer(objectType)
Dim aStream As System.IO.MemoryStream = New System.IO.MemoryStream(xmlbytearr)
Return serializer.Deserialize(aStream)
End Function