如何在继承的ViewModels中处理MustOverride(虚拟)属性

时间:2018-06-29 01:20:03

标签: c# wpf vb.net mvvm polymorphism

我正在尝试在MVVM WPF应用程序的数据库中在屏幕上创建所有动物的列表,但是该列表必须包含特定于动物各自性别的属性(以类表示)。

该模型由 <?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"> <changeSet author="OK (generated)" id="1530226079041-1"> <insert tableName="TT"> <column name="TS_LOADED"/> <column name="TS_GENERATED" valueDate=~your generated timestamp value here. in my case it's "2018-06-28 22:47:38.816343"/> </insert> </changeSet> </databaseChangeLog> <?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"> <changeSet author="OK" id="3"> <insert tableName="TT"> <column name="TS_LOADED" valueDate=~value in TS_GENERATED from previous step, i.e."2018-06-28 22:47:38.816343"~/> </insert> </changeSet> </databaseChangeLog> 类组成,这些类继承自 <?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"> <changeSet author="OK" id="3"> <insert tableName="TT"> <column name="TS_LOADED" valueDate=~value in TS_GENERATED from previous step, i.e."2018-06-28 22:47:38.816343"~/> </insert> </changeSet> </databaseChangeLog> Following this example,因此ViewModel也分为MaleFemale,它们都继承自下面的通用MustInherit Animal

MaleViewModel

我还创建了一个FemaleViewModel ViewModel,它的MustInherit AnimalViewModel属性绑定到View的UserControl。我想将正确的ViewModel类型添加到此列表中,但是它是invalid to cast a base type to an inherited type,就像我在以下代码中尝试过的那样。

Public MustInherit Class AnimalViewModel(Of T as Animal)
    Inherits GalaSoft.MvvmLight.ViewModelBase

    Public Property Animal As T

    Protected Sub New(NewAnimal as T)
        Me.Animal = NewAnimal
    End Sub

    Public Overrides Function ToString() as String
        Return String.Format("{1}{2} ""{3}"" | {4}",
                             Me.Animal.RightEarTag,
                             Me.Animal.LeftEarTag,
                             Me.Animal.ShortName,
                             Me.SexIdentifierName)
    End Function

    'Makes a distinction between "bull", "cow", "steer", "heifer",
    'or other classes as needed
    Public MustOverride Function SexIdentifierName as String

End Class

Public Class MaleViewModel
    Inherits AnimalViewModel(Of Male)

    Public Sub New(AnAnimal as Male)
        MyBase.New(AnAnimal)
    End Sub

    Public Overrides Function SexIdentifierName as String
        'Logic goes here
    End Function
End Class

处理这些计算得出的MustOverride属性的最佳方法是什么?我考虑过

  1. 将其实现升级到AnimalListWorkspace

  2. 更改数据库对象以专门检索AnimalListPublic Class AnimalListWorkspace Inherits WorkspaceViewModel Public ReadOnly Property AnimalList as IEnumerable(Of AnimalViewModel(Of Animal)) Get Dim animalVmList = New List(Of AnimalViewModel(Of Animal)) For Each an in AnimalDatabase.Animals If TypeOf an Is Male Then animalVmList.Add(New MaleViewModel(Ctype(an, Male))) ElseIf TypeOf an Is Female Then animalVmList.Add(New FemaleViewModel(Ctype(an, Female))) Else Throw New InvalidCastException("Unknown sex/type of animal") End If Next Return animalVmList End Get End Property

这些解决方案可能适用于此示例,因为继承的成员很少,但是它们看起来紧密相连,以后很难重构。

1 个答案:

答案 0 :(得分:0)

类型参数似乎是不必要的。基类的构造函数接受Animal并且仅知道动物。 MaleAnimal的特定类型。以下应该可以使用,即您可以将任何类型的特定AnimalViewModel添加到List(Of AnimalViewModel)

查看模型:

Public MustInherit Class AnimalViewModel
    Inherits GalaSoft.MvvmLight.ViewModelBase

    Public Property Animal As Animal

    Protected Sub New(NewAnimal As Animal)
        Me.Animal = NewAnimal
    End Sub

    Public Overrides Function ToString() As String
        Return String.Format("{1}{2} ""{3}"" | {4}",
                             Me.Animal.RightEarTag,
                             Me.Animal.LeftEarTag,
                             Me.Animal.ShortName,
                             Me.SexIdentifierName)
    End Function

    Public MustOverride Function SexIdentifierName() As String

End Class

Public Class MaleViewModel
    Inherits AnimalViewModel

    Public Sub New(AnAnimal As Male)
        MyBase.New(AnAnimal)
    End Sub

    Public Overrides Function SexIdentifierName() As String
        Return "Male"
    End Function
End Class

型号:

Public Class Animal
    Public Property RightEarTag As String
    Public Property LeftEarTag As String
    Public Property ShortName As String
End Class

Public Class Male
    Inherits Animal

End Class

工作区:

Public Class AnimalListWorkspace

    Public ReadOnly Property AnimalList As IEnumerable(Of AnimalViewModel)
        Get
            Dim animalVmList = New List(Of AnimalViewModel)

            For Each an In AnimalDatabase.Animals
                If TypeOf an Is Male Then
                    animalVmList.Add(New MaleViewModel(CType(an, Male)))
                ElseIf TypeOf an Is Female Then
                    animalVmList.Add(New FemaleViewModel(CType(an, Female)))
                Else
                    Throw New InvalidCastException("Unknown sex/type of animal")
                End If
            Next

            Return animalVmList
        End Get
    End Property
End Class