Любой способ передачи определения универсального типа в asmx webservice - PullRequest
1 голос
/ 08 февраля 2012

Я использую вызовы jQuery ajax к веб-службам ASP.Net (файлы ASMX) для обновления данных веб-страницы.

У меня есть код для хранения базы данных, отдельный от кода класса объекта домена (в примере кода ниже)есть класс Animal и класс AnimalRepository).Я реализую соглашение, что все подобные классы репозитория объектов домена будут иметь метод Store.

Я хотел бы создать веб-сервис, который может обслуживать вызов метода Store для любого из этих классов репозитория.Чтобы это работало, в приведенном ниже примере кода параметр List (Of Animal) должен быть универсального типа.

Я пытался использовать List (Of Object), но ошибка команды Store при невозможностиконвертировать типы.Я не думаю, что могу привести List (Of Object) к нужному типу, так как он не известен до времени выполнения.

    <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

В идеале мне бы хотелось:

    <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

В определении метода веб-сервиса нет места для обобщений, но есть хитрость для достижения того же конечного результата.В противном случае я собираюсь создать множество таких веб-сервисов Store *, которые отличаются только по первому параметру.

Ответы [ 2 ]

2 голосов
/ 08 февраля 2012

Обобщения не имеют никакого значения в мире веб-сервисов.

Вы не можете никуда прийти закрыть с помощью ASMX.С WCF вы можете что-то делать, но вы не можете использовать открытый универсальный тип в операционном контракте.

1 голос
/ 08 февраля 2012

Если вы знаете, какой тип объекта вы ожидаете, вы можете сериализовать байтовый массив List (of Animal) и вместо этого десериализовать объект из байтового массива.

Я сделал небольшой пример, хотя в VB.NET, но я думаю, что вы можете перевести его. Я создал класс, который используется и веб-службой, и клиентом.

Код клиента

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

Общая библиотека

 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

Веб-сервис

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