Расширение Общие методы в .NET (VB.NET) - PullRequest
0 голосов
/ 10 ноября 2010

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

Скажем, я хочу

Dim cust1 as New Customer() //...
Dim cust2 as New Customer() //...

cust2 = cust1.Clone()

''
' My extension method '
''
<Runtime.CompilerServices.Extension()> _
Public Function Clone(Of T As {Class, New})(ByVal obj As T) As T 
  Dim objClone As New T
    ' clonning stuff '
    ' objClone = CType(GetAnObjClone(), T) '
  Return objClone
End Function

    Dim c As MyObject
    Dim cc As MyObject = c.Clone() ' does work!!! cool... '

вопрос для удаления.

Ответы [ 2 ]

5 голосов
/ 10 ноября 2010

Клонирование должно быть чем-то, что сам объект выполняет как обычный метод, а не как метод расширения.См. документацию MSDN для MemberwiseClone для примера.

0 голосов
/ 02 декабря 2010

Я фактически сделал нечто подобное, используя отражение, чтобы помочь с привязкой модели в проекте MVC.Я определил пользовательский атрибут "Updatable" и общий метод расширения.Это немного безопаснее, поскольку я должен явно пометить атрибуты, которые будут клонированы, с моим настраиваемым атрибутом (или через класс метаданных), чтобы поведение могло что-либо делать, но я уверен, что вы могли бы адаптировать его для своих собственных целей.

Вот мой пользовательский атрибут (не очень захватывающий!)

<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)>
Public Class UpdateableAttribute : Inherits Attribute

End Class

А вот и метод расширения

<Extension()>
Public Sub UpdateObject(Of T)(ByVal targetObject As T, ByVal otherObject As T)
    Dim metaDataType As MetadataTypeAttribute = GetType(T).GetCustomAttributes(GetType(MetadataTypeAttribute), True).FirstOrDefault
    If metaDataType Is Nothing Then
        For Each prop As Reflection.PropertyInfo In GetType(T).GetProperties()
            If prop.GetCustomAttributes(GetType(UpdateableAttribute), True).Count > 0 Then
                Dim targetValue = prop.GetValue(targetObject, {})
                Dim otherValue = prop.GetValue(otherObject, {})
                If Not targetValue = otherValue Then
                    prop.SetValue(targetObject, otherValue, {})
                End If
            End If
        Next
    Else
        Dim targetProps As Reflection.PropertyInfo() = GetType(T).GetProperties()
        For Each prop As Reflection.PropertyInfo In metaDataType.MetadataClassType.GetProperties()
            If prop.GetCustomAttributes(GetType(UpdateableAttribute), True).Count > 0 Then
                Dim propName As String = prop.Name
                Dim targetProperty = targetProps.Single(Function(p) p.Name = propName)
                Dim targetValue = targetProperty.GetValue(targetObject, {})
                Dim otherValue = targetProperty.GetValue(otherObject, {})
                If Not targetValue = otherValue Then
                    targetProperty.SetValue(targetObject, otherValue, {})
                End If
            End If
        Next
    End If
End Sub

Хорошо для меня, он, очевидно, использует отражение такне молниеносно, но спасает меня от большого количества левого = правого кодирования.

Если у вас есть доступ к целевому классу, вы можете просто сделать это, в этом примере клонируются только имя и фамилия.

Public Class Person
    <Updateable()>
    Public Property FirstName As String
    <Updateable()>
    Public Property Surname As String
    Public Property ShoeSize As Integer
    Public Property Gender As Gender
    Public Property BirthDate As DateTime
    Public Property FavoriteCarMake
End Class

И пример использования класса метаданных для того же, что хорошо, если вы не можете редактировать целевой класс напрямую (например, классы Entity Framework, если вам не нравится редактировать шаблоны T4)

<MetadataType(GetType(PersonMetadata))>
Public Class Person
    Public Property FirstName As String
    Public Property Surname As String
    Public Property ShoeSize As Integer
    Public Property Gender As Gender
    Public Property BirthDate As DateTime
    Public Property FavoriteCarMake
End Class

Public Class PersonMetadata

    <Updateable()>
    Public Property FirstName

    <Updateable()>
    Public Property Surname

End Class

В обоих случаях вы можете просто сделать что-то вроде этого:

Dim person1 As New Person With ...
Dim person2 As New Person With ...

person1.UpdateObject(person2)
...