|
-
Sep 13th, 2015, 04:41 AM
#1
Thread Starter
Frenzied Member
Need help with generics and base classes
Hi!
I am trying to apply some refactoring to a viewmodel class, but I am fairly stuck. We had validation logic in every view model, and the code looked very repetitive, so I figured I should put int in our ViewModelBase class. But it just won't work correctly.
I have two problems:
1) Should I really need a generic base class where T is the same type as the inheriting class? Feels like it is the same thing...
2) In the base class I need to use an extension method that only seems to be available in a derived class. We are using FluentValidator library.
Here is the code:
Code:
Public Class MainViewModel
Inherits ViewModelBase(Of MainViewModel)
Implements IDataErrorInfo
Private _price As System.Nullable(Of Decimal)
Public Property Price() As System.Nullable(Of Decimal)
Get
Return _price
End Get
Set
SetProperty(_price, value)
Debug.WriteLine("Price set to:{0}", value)
End Set
End Property
Public _name As String
Public Property Name() As String
Get
Return _name
End Get
Set
SetProperty(_name, value)
End Set
End Property
Public Sub New(validator As AbstractValidator(Of MainViewModel))
MyBase.New(validator)
End Sub
End Class
Public MustInherit Class ViewModelBase(Of Tv)
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler
Public Property Validator() As AbstractValidator(Of Tv)
Get
Return m_Validator
End Get
Set
m_Validator = Value
End Set
End Property
Private m_Validator As AbstractValidator(Of Tv)
Private _errors As Dictionary(Of String, String)
Public Sub New(validator__1 As AbstractValidator(Of Tv))
Validator = validator__1
_errors = New Dictionary(Of String, String)()
End Sub
Protected Sub SetProperty(Of T)(ByRef field As T, value As T, <CallerMemberName> Optional name As String = "")
If Not EqualityComparer(Of T).[Default].Equals(field, value) Then
field = value
Dim handler = PropertyChanged
RaiseEvent handler(Me, New PropertyChangedEventArgs(name))
End If
End Sub
Public Default ReadOnly Property Item(propertyName As String) As String
Get
Dim errors As String = String.Empty
If Validator IsNot Nothing Then
_errors.Remove(propertyName)
Dim results = Validator.Validate(Me, propertyName)
If results IsNot Nothing AndAlso results.Errors.Count > 0 Then
errors = String.Join(Environment.NewLine, results.Errors.[Select](Function(x) x.ErrorMessage).ToArray())
_errors.Add(propertyName, errors)
End If
End If
[Error] = [String].Join(Environment.NewLine, _errors.[Select](Function(x) x.Value).ToArray())
Return errors
End Get
End Property
Private _error As String
Public Property [Error]() As String
Get
Return _error
End Get
Set
SetProperty(_error, value)
End Set
End Property
End Class
There is an implementation of MainViewModelValidator where the validation logic is contained. That should be injected to MainViewModel through constructor and passed down to the base class. The real issue I think is the declaration of the property that holds the Validator. From what I understand, this has to be a generic with a specific type, hence I need to pass down the type T of the MainViewModel, so I can declare a property that holds my validator.
The next problem is the Validator.Validate line which won't compile because this particular signature of Validate with 2 parameters is an extensionmethod and not available in the AbstractValidator(of T) base class. Should I do some kind of cast here or what?
It feels like I am on the right track here, but this is my first attempt with generics and I feel kind of lost.
please help me out, it would save us tons of code since we have like 20 viewmodels with the same validator code...
cheers
Henrik
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|