|
-
January 2nd, 2009, 09:21 AM
#16
Re: Help creating interface.
 Originally Posted by Marraco
...So, I need to fill in the blanks.
The delegate in the common array is the unique connection between the class who manage the files, and any other class, so the unique thing that UnRegister function does, is to delete the delegate from the common array.
[Vb.NET 2008 (ex Express)]
-
January 2nd, 2009, 10:28 AM
#17
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
...
I'm not sure what you are trying to do here. From your first description it sounds like you are loading data then passing each chunk of data to one or more objects...
I think that Explaining more would make more noise than help, but this is a bare bones skeleton of my code:
Code:
Imports WindowsApplication1.MyModule.FileLoader
Imports WindowsApplication1.MyModule.FileLoader.ValidationResult
Public Class Form1
'...
End Class
Public Module MyModule
Public Class FileLoader
Public Shared ValidatorsList As New PersonalizedList(Of Validator)
Public Delegate Function Validator(ByRef ThisLine As ReadData) As ValidationResult
Public Class PersonalizedList(Of Type)
Inherits SortedList
Public Function GetValidKeys() As String()
'...
End Function
Public Sub validate()
'...
End Sub
Public Sub Add(ByVal SomeDelegate As Validator)
'...
End Sub
Public Sub Remove(ByVal SomeDelegate As Validator)
'...
End Sub
End Class
Public MustInherit Class ValidationResult
Public Structure ReadData
'...
End Structure
Public MustOverride Function ShouldValidate() As Boolean
Public MustOverride Sub Validate()
End Class
Public Interface IValidatorInterface
Sub Register()
Sub UnRegister()
End Interface
'All This mess is to call this
Public Sub New(ByVal FileName As File)
For Each Line In FileName
For Each Key In ValidatorsList.GetValidKeys(Line)
ValidatorsList(Key).Validate()
Next
Next Line
End Sub
End Class
Public Class SomeClass
Implements IValidatorInterface
Implements IDisposable
Public Sub Register() Implements FileLoader.IValidatorInterface.Register
ValidatorsList.Add(AddressOf MyClassValidator)
End Sub
Public Sub UnRegister() Implements FileLoader.IValidatorInterface.UnRegister
ValidatorsList.Remove(AddressOf MyClassValidator)
End Sub
Public Function MyClassValidator(ByRef ThisLine As ReadData) As ValidationResult
...
End Function
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free other state (managed objects).
UnRegister()
End If
' TODO: free your own state (unmanaged objects).
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Module
Last edited by Marraco; January 2nd, 2009 at 10:40 AM.
Reason: Corrected some generic code
[Vb.NET 2008 (ex Express)]
-
January 2nd, 2009, 06:07 PM
#18
Re: Help creating interface.
Ok, I have a better idea of what your trying to do. However, it still seems wierd that you can have multiple objects that can process the same data.
I don't see the point of using delegates. They're generally used in response to handling events. When loading data you should directly call functions to validate the input. delegates would created unneeded overhead.
I think I may of misunderstood what you had said earlier. I thought you wanted to use reflection to find each instance of certains classes. However, I realize now that you probably wanted to use reflection to find every class that can process your data. If you put all your classes in a module then you can use reflection to search for these objects.
Looks like you made a couple posts while I was typing up a code example. However, it still looks like my example will help.
It looks for all objects in a module that has certain methods. In my example, I have a shared method that is used to determine is the class can process the data or not. interfaces can't define shared methods so I had to check to see if the method was a member. If you need instance members you can make that part of a interface and simply check if the class implements the interface. I didn't check the properties or the return type of the shared method. I thought I let that be an exercise for you.
Well, he's my code example,
Code:
Module Module2
Public Class Data
Public Processors As New List(Of Processor)
Public Sub LoadDataFile(ByVal filePath As String)
Dim type As Type = GetType(ProcessingObjects)
' Verify all objects in 'Module ProcessingObjects' have what they need
Dim memberInfo As MemberInfo() = type.GetNestedTypes()
For i As Integer = 0 To memberInfo.Count - 1
Dim currentType As Type = type.GetType(memberInfo(i).ToString())
Dim baseType As Type = currentType.BaseType
If baseType.Name() <> "Processor" Then
Throw New Exception("Error: " + currentType.Name() + " does not inherit from Processor")
End If
Dim method As MemberInfo = currentType.GetMethod("CanProcessLine")
If method Is Nothing Then
Throw New Exception("Error: " + currentType.Name() + " does not have CanProcessLine")
End If
Next
' Load each line of data file.
' For each line for every class that can process that line and add it to the list of processors
Dim lines As String() = File.ReadAllLines(filePath)
For i As Integer = 0 To lines.Count - 1
For j As Integer = 0 To memberInfo.Count - 1
Dim currentType As Type = type.GetType(memberInfo(j).ToString())
' Call the shared member "CanProcessLine" to see if the class can
Dim args() As String = {lines(i)}
Dim useIt As Boolean = CBool(currentType.InvokeMember("CanProcessLine", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.Static Or BindingFlags.InvokeMethod, Nothing, Nothing, args))
If useIt Then
' if so, create an instance and add to list
Dim processor As Processor = CType(Activator.CreateInstance(currentType, args), Module2.Processor)
Processors.Add(processor)
End If
Next
Next
End Sub
End Class
Public MustInherit Class Processor
Protected Data As String
Public Sub New(ByVal info As String)
Data = info
End Sub
End Class
End Module
Module ProcessingObjects
Public Class DataType1
Inherits Processor
Public Sub New(ByVal data As String)
MyBase.New(data)
End Sub
Public Shared Function CanProcessLine(ByVal line As String) As Boolean
If line.StartsWith("1") Then
Return True
End If
Return False
End Function
End Class
Public Class DataType2
Inherits Processor
Public Sub New(ByVal data As String)
MyBase.New(data)
End Sub
Public Shared Function CanProcessLine(ByVal line As String) As Boolean
If line.StartsWith("2") Then
Return True
End If
Return False
End Function
End Class
End Module
-
January 5th, 2009, 04:11 PM
#19
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
Ok, I have a better idea of what your trying to do. However, it still seems weird that you can have multiple objects that can process the same data.
I don't see the point of using delegates.
Well, in fact, first, I where thinking on send the entire object reference (instead of delegates), but that way, I was forced to expose some private instances, only to expose a single routine. By the way, I could not pass Me as parameter, so I thinked on passing a pointer to the instance function. That lead me to delegates. After it, I read that a new version of VB.NET (2008?) allows a specific "Function" type. Probably it is a better solution. Not investigated.
As I see, a delegate purpose is to encapsulate a pointer to a function.
 Originally Posted by Scott.Macmaster
They're generally used in response to handling events. When loading data you should directly call functions to validate the input. delegates would created unneeded overhead.
Although is more complex than this, for example, a line can contain the path of a file. Then, I have objects whose responsibility is to manage files, so I want those objects to check if the path is valid, and if not, mark them as unknown path. I don't want other classes messing with files. I have only one module managing all files, and it should not allow any other to touch them.
But then, I have some classes which need a given set of files. For example, any file with extension ".RST" should have also a file ".RDC", and both files need to satisfy a given data structure. That is a specific requirement, who need to be coded on the class who needs it. I can't move his code to other place, otherwise, I can loose track on who is related to that piece of code.
Anyway, I cannot let a third class to open files to check them. The third class, then defines a regular expression, for each kind of file, and is the file manager class who open the file, check it with the regular expression, and closes it.
... and that file path, is related to a given point on a map. Then another class, who manages points on maps, need to identify that point, and check than the line makes sense from his own viewpoint. ¿the location exists? ¿The text is misspelled? ¿a new instance of PointsOnTheMap class need to be created, or this data need to be added on an existing instance?
... and there exists already i7 processors whit 8 virtual cores. (Saddly, I still have not one ( )), So, in the future, I want all those tasks to be capable of run in parallel.
isolating each checking and data processing code, on his own class, requires to define the way each class should behave. Do it class need to access files? Not so easy. It need to agree to a standard, who the file manager rules. A way to force them to adhere to the standard, is to define an interface, so when I need to write the code to access that file, I need to implement the interface. It forces me to no forget to code something, otherwise the compilator rant and whine until I fix the bugs.
¿is there a better way? No idea.
 Originally Posted by Scott.Macmaster
I think I may of misunderstood what you had said earlier. I thought you wanted to use reflection to find each instance of certains classes. However, I realize now that you probably wanted to use reflection to find every class that can process your data. If you put all your classes in a module then you can use reflection to search for these objects.
I don't care if is about Reflection. It only need to do the job, and in a reliable way.
For example, this station contains rain data? I should ask his class if it contains rain data, and then what to do. ¿contains temperature data? Is not my business to decide if it contains temperature data, I should call a class managing temperature.
¿What if tomorrow, some stations add a wild guinea pig counting? I want to write a class named GuineaPigClass. I don't want to recode other code out of the new GuineaPigClass. At startup time, my old code automatically would search for a new class implementing the interface, use it to ask the new class if a given place have anything to do with guinea pig, and if true, then run the guinea pig code.
I don't know how many new classes I can write in the future, which a given interface, or how many instances would do different things.
What new data I gonna read from the file in the future? Don't know. How to validate that data? don't know. But if it contains a file path, I don't want to write again code I already have. The file path would be automatically checked.
And If Nobody checked a given line, then some bug is present, Probably some coding work was left in the task list.
---------------
 Originally Posted by Scott.Macmaster
...
Well, he's my code example,
It anyway need to know what module contains a class implementing the interface.
I tried to seam it whit this another code, who founds any class implementing the interface:
(Note: If somebody finds this web page with Google probably want this code, because I asked Is there a way to find all classes ... which implement a given Interface?)
Code:
Dim asm As Reflection.Assembly = Reflection.Assembly.Load("MyAssemblyName")
Dim types As Type() = asm.GetTypes()
Dim Implementators As Object = types.Where(Function(x) x.GetInterface("IMyInterface") IsNot Nothing)
I like this other a bit more (taken from here):
Code:
Dim type As Type = GetType(IMyInterface)
Dim Implementators As IEnumerator = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(Function(f) f.GetTypes()).Where(Function(g) type.IsAssignableFrom(g))
It returns the list of classes which implements a given interface, although I have done nothing useful with it, because, although it accept being declared as Object, or Ienumerable, they don't are cast to that types. Also cannot be cast as array of Type.
I cannot even tell what type is contained in "Implementators" variable. GetType returns a mess, or crashes.
-----------
Last edited by Marraco; January 5th, 2009 at 04:22 PM.
[Vb.NET 2008 (ex Express)]
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
|