|
-
December 29th, 2008, 08:26 AM
#1
Help creating interface.
Is there a way to find all classes (In fact, all instances) which implement a given Interface?
I are thinking of force the interface to add a reference of himself to a global array.
Each .new() constructor of each class should run the interface routine to add the instance being initialized to a shared global array.
But it looks like an interface cannot be defined with a shared variable (is not a class), so I gonna need to add a new data definition, which can be trouble to track is related to the interface, and worst, it would clutter my code.
Probably exist a better way.
Some tips?
[Vb.NET 2008 (ex Express)]
-
December 29th, 2008, 08:41 PM
#2
Re: Help creating interface.
This seems like a very unusually requirement and probably a bad design. If you give some more details I could suggest a better alternative. In the meantime I have a suggestion for adding all instances to a global variable. However, there are 2 major issues with this. Someone could create a local instance of the global object. Also, this would result in major memory leaks if you aren't careful about removing references to unused instances of the objects you are tracking.
Code:
Public Class Tracker
Private Instances As List(Of SpecialClass)
Public Sub Add(ByVal obj As SpecialClass)
Instances.Add(obj)
End Sub
End Class
Public Class SpecialClass
Private Sub New()
End Sub
Public Shared Function GiveMeANewOne(ByVal tracker As Tracker) As SpecialClass
Dim obj As New SpecialClass()
tracker.Add(obj)
Return obj
End Function
End Class
If you implement ths in a dll you should be able to prevent creation of local Trackers. However, you still have the issue of memory leaks.
-
December 30th, 2008, 08:57 AM
#3
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
This seems like a very unusually requirement and probably a bad design.
I agree, bad design. But I don't know how to do it the "right" way.
 Originally Posted by Scott.Macmaster
If you give some more details I could suggest a better alternative.
I Read data from a file. I organize read data in groups Data A, Data B, ... Data N.
Each Data X may be processed by different classes like Class X, Class Y, Class Z. Is each class who defines if it need to process a given kind of data, and many unrelated class can process the same data (or portion of that data).
I want to add a new class, and automatically have it capable of process Data N by defining a Interface FunctionForDataN for process of Data N.
The basic idea was, make each Data N to search for any class . If her supports an Interface FunctionForDataN, then execute that Interface.
I have no Idea on how to do it. I had searched on Reflection, but got no useful solution.
I had implemented a .Register() sub on the Interface FunctionForDataN, so each class implementing that Interface, should call the .Register function on his .New constructor, passing a Delegate to the local interface implementation.
 Originally Posted by Scott.Macmaster
In the meantime I have a suggestion for adding all instances to a global variable. However, there are 2 major issues with this. Someone could create a local instance of the global object. Also, this would result in major memory leaks if you aren't careful about removing references to unused instances of the objects you are tracking.
...
If you implement ths in a dll you should be able to prevent creation of local Trackers. However, you still have the issue of memory leaks.
Memory leaks. I had not think on it. Maybe I should add a .Dispose routine to .Unregister
[Vb.NET 2008 (ex Express)]
-
December 30th, 2008, 08:08 PM
#4
Re: Help creating interface.
The garbage collector in .Net will only free up the memory used by objects after the last reference to the object is removed. I assume your Unregister() method removes references from a list so there's nothing else you can add to that to deal with memory leaks. I'm not sure what you mean by adding Dispose to it. Dispose is a required function for objects that implement IDisposable. But that doesn't guarantee cleanup if you forget to call Unregister() for every object. You could wrap that in a Using/End Using. However, you still have to remember to use Using/End Using each time. I'm still not sure what you are trying to do. However, I don't think tracking all these objects is the solution.
I briefly looked at the members of the garbage collector but I don't see anything that would list all the objects it's managing. If there was you could loop through and find all instances of your object. However, you should leave the GC along. It works just fine unless your doing something bad.
Reflection won't help at all since it's job is to examine data types. It doesn't do anything with instances of objects.
I kinda' get the impression that you are loading a file that list instructions for doing things. Maybe the following code will help.
Code:
Public Class Instructions
Public Instructions As New List(Of Instruction)
Public Sub ProcessInstructions()
For Each Instruction In Instructions
Instruction.ProcessData()
Next
End Sub
End Class
Public MustInherit Class Instruction
Protected Data As String
Public MustOverride Sub ProcessData()
End Class
Public Class Soup
Inherits Instruction
Public Overrides Sub ProcessData()
If Data = "Chicken" Then
MakeChickenSoup()
End If
End Sub
End Class
-
January 1st, 2009, 10:12 AM
#5
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
The garbage collector in .Net will only free up the memory used by objects after the last reference to the object is removed. I assume your Unregister() method removes references from a list so there's nothing else you can add to that to deal with memory leaks. I'm not sure what you mean by adding Dispose to it. Dispose is a required function for objects that implement IDisposable.
I added Implements IDisposable to the user base class for processing data:
Code:
Public Interface IFunctionForDataN
Sub Register()
...
Sub UnRegister()
End Interface 'IFunctionForDataN
Code:
Public MustInherit Class ValidateFileData
Implements IDisposable
Implements IFunctionForDataN
#Region " IFunctionForDataN "
Sub New()
...
Register()
End Sub
... 'Another interface code
MustOverride Sub Register()... adding MyDelegates to an ICollection
...
MustOverride Sub UnRegister()... Deleting MyDelegates from ICollection
#End Region '" IFunctionForDataN "
...
#Region " IDisposable Support "
Protected disposedValue As Boolean = False ' To detect redundant calls
Protected Sub Dispose(ByVal disposing As Boolean)
Unregister()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region '" IDisposable Support "
...
End Class 'ValidateFileData
(Not sure on what to do with disposedValue variable. )
 Originally Posted by Scott.Macmaster
But that doesn't guarantee cleanup if you forget to call Unregister() for every object. You could wrap that in a Using/End Using. However, you still have to remember to use Using/End Using each time. I'm still not sure what you are trying to do. However, I don't think tracking all these objects is the solution.
...
I like your idea on GiveMeANewOne() this way
Code:
Public Class SpecialClass
Inherits ValidateFileData
...
Public Shared Function GiveMeANewOne(ByVal Parameters As SpecialClass.SpecialParameters) As SpecialClass
Dim obj As New SpecialClass(Parameters)
obj.Register()
Return obj
End Function
End Class
Because My New() on my Base class, although nicely .Register() automatically any inherited class, does not allow me to override or overload the .New() constructor, and forces me to put MyBase.New() only as the first line on the children .New(). It does not let me pass arbitrary parameters to the constructor, to initialize variables before registering.
The bad side of it, is that I can forget to add the obj.Register() line.
The Interface IFunctionForDataN, with [MustInherit] MustOverride Sub Register() warrant that I never would forget to write the Register() sub, -Otherwise, .NET would kick my *** until I write them- but nothing warrant that I would add the obj.Register() line on Function GiveMeANewOne.
Last edited by Marraco; January 1st, 2009 at 12:16 PM.
Reason: To make it more clear
[Vb.NET 2008 (ex Express)]
-
January 1st, 2009, 11:47 AM
#6
Re: Help creating interface.
Remember two "rules"
1) It MUST be safe to call Dispose() on an instance multiple times.
2) It is suggested that accessing any method (other than disposed) or propertyy on a disposed object throw an ObjectDisposed() exception.
This answers your qeustion about what to do with the variable.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 1st, 2009, 12:13 PM
#7
Re: Help creating interface.
 Originally Posted by TheCPUWizard
Remember two "rules"
1) It MUST be safe to call Dispose() on an instance multiple times.
2) It is suggested that accessing any method (other than disposed) or propertyy on a disposed object throw an ObjectDisposed() exception.
This answers your qeustion about what to do with the variable. 
Did it mean something like this?:
Code:
#Region " IDisposable Support "
Protected disposedValue As Boolean = False ' To detect redundant calls
Protected Sub Dispose(ByVal disposing As Boolean)
Unregister()
disposedValue = true
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region '" IDisposable Support "
And then adding to any public function/sub/property?:
Code:
If disposedValue Then Throw New ObjectDisposedException("AArrrgg")
[Vb.NET 2008 (ex Express)]
-
January 1st, 2009, 12:18 PM
#8
Re: Help creating interface.
 Originally Posted by Marraco
Did it mean something like this....
And what exactly happens when the following code is called TWICE:
Code:
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 1st, 2009, 01:22 PM
#9
Re: Help creating interface.
 Originally Posted by TheCPUWizard
And what exactly happens when the following code is called TWICE:
I guess, it should be:
Code:
Public Sub Dispose() Implements IDisposable.Dispose
If disposedValue Then
Throw New ObjectDisposedException("AArrrgg")
else
Dispose(True)
GC.SuppressFinalize(Me)
End If
End Sub
¿Its right?
(I need to read more about this stuff)
[Vb.NET 2008 (ex Express)]
-
January 1st, 2009, 01:30 PM
#10
Re: Help creating interface.
 Originally Posted by Marraco
I guess, it should be:
You guessed wrong. Go back and reat Reul #1 (In reply #6)
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 1st, 2009, 01:32 PM
#11
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
The garbage collector in .Net will only free up the memory used by objects after the last reference to the object is removed. I assume your Unregister() method removes references from a list so there's nothing else you can add to that to deal with memory leaks. I'm not sure what you mean by adding Dispose to it. Dispose is a required function for objects that implement IDisposable. But that doesn't guarantee cleanup if you forget to call Unregister() for every object. You could wrap that in a Using/End Using. However, you still have to remember to use Using/End Using each time. I'm still not sure what you are trying to do. However, I don't think tracking all these objects is the solution.
For objects which have meaningful Dispose implementations (this one does not seem to), the following can be used ON DEVELOPMENT BUILDS to validate the usage...
1) Make sure that Dispose() causes a GC.SuppressFinalize() call. (It always should!)
2) Have the Finalizer (which should never be invoked) record the fact in some manner (Exception, LogFile, ext). Just be carefuly to handle the "AppDomain teardown" condition.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 1st, 2009, 02:05 PM
#12
Re: Help creating interface.
 Originally Posted by TheCPUWizard
1) It MUST be safe to call Dispose() on an instance multiple times.
...
As I see, the only unsafe thing it can occur, is a repeated calling to UnRegister(), because, it may try to operate on data that was modified/destroyed/disposed at the before UnRegister() Call.
I suppose that UnRegister destroy any external reference to my internal Class data.
Register call another class, to accept a delegate as parameter. (Is only stored on an List(Of DelegateType))
UnRegister call the same Class to erase that delegate, and is That class who should warrant, deleting any copy of data received (I think it haves only one copy)
Is not clear if is safe to call GC.SuppressFinalize(Me) again.
[Vb.NET 2008 (ex Express)]
-
January 1st, 2009, 08:44 PM
#13
Re: Help creating interface.
The details of using IDisposable are irrelevant here. Unless you left something out everything you have is managed code. Basically, you have a list contained in a class. The system will automatically free the memory. Because of that you don't need Unreqister(). You don't really need Register(). Unless you're doing additional processing there, just add the object to the list and drop the call to Register().
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. These objects then not only do processing on their data but also on data from other objects. Creating a highly complicated level of coupling.
I'd suggest a more hierarchical approach. Maybe I could offer a suggestion if you tried to explain what this data is and what you are trying to do with it.
Scott
-
January 1st, 2009, 09:02 PM
#14
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
The details of using IDisposable are irrelevant here.
Depends on your point of view. I 100% agree with Disposable not being germane to the problem
 Originally Posted by Reply #11
For objects which have meaningful Dispose implementations (this one does not seem to),
But IF IDisposable is implemented, then an incorrect implementation will only cause additional problems. [While a correct one will have no net impact on the situation]
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 2nd, 2009, 09:08 AM
#15
Re: Help creating interface.
 Originally Posted by Scott.Macmaster
The details of using IDisposable are irrelevant here. Unless you left something out everything you have is managed code. Basically, you have a list contained in a class. The system will automatically free the memory. Because of that you don't need Unreqister(). You don't really need Register(). Unless you're doing additional processing there, just add the object to the list and drop the call to Register().
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. These objects then not only do processing on their data but also on data from other objects. Creating a highly complicated level of coupling.
I'd suggest a more hierarchical approach. Maybe I could offer a suggestion if you tried to explain what this data is and what you are trying to do with it.
This is a description of the frame. It write it only as information:
I are updating an VB6 application, to VB.NET. I are totally reengineering it because it was full of bugs.
So, I have the new application separated on a number of classes, and his inherited classes. They can grow, and I can make new ones, as I continue upgrading the VB6 app.
So, now, I have this situation:
I have a text file, Since it was inherited from a VB6 application, it can be edited by user. And users are prone to make mistakes.
So, at load times, an undefined number of classes need to check each read data, to check for validity. If a given line of the text file is not valid, the class checking it need to:
- Say that it is not valid.
- Say Why is not valid.
- Give an user readable text to advice the user (or to be stored in a log file).
- Adopt some measure to manage the data if is not totally broken.
- Flag the data as invalidated, so no other class uses it, expecting it to work.
In the VB6 version, the same routine that readed the file was doing all the checking, but that was prone to bugs, because the classes that really use the data where unrelated to the checkings, and changing anything in some class generated bugs on the reading routine.
So, now each class is responsible for managing anything that should be internal, as checking for data validity from his own viewpoint.
I implemented the validation code as an Interface.
The interface defines a delegate who need to have each class capable of Checking.
The Interface defines a boolean function to tell If a given class implementing it should check a given line of data.
Also defines a function .Register(), because i have "no idea" (and I think is good to assume it) who, or how many classes would implement that Interface, so each class need to add a delegate to a common Interface array, to the file, after reading each line, can find all the classes who can manage it, and run his Checking routines. This is my basic problem. I don't know what classes implement the interface, and I want to automate it as much as possible, so I reduce future coding, and I want to the .NET environment to kick my azz if I forget to implement a key routine.
For that reason, I need the .Register interface function, who add delegates to a common array.
now, Macmaster post (
 Originally Posted by Scott.Macmaster
... this would result in major memory leaks ...
)
The problem is, what if a given instance of a class stops existing? (I think no one should stop existing, but want no to leave broken tips on the code), so, it need to have an unregister function.
Since I read on Internet that I should implement the .Dispose routine, to have the Unregister function automatically executed, then, as I understood, any class capable of unregister automatically should implement the IDisposable interface. When you write "Implements Idisposable", the .NET environment automatically add this code:
Code:
Public Class UnregisterCapable
Implements IDisposable
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).
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
So, I need to fill in the blanks.
Last edited by Marraco; January 2nd, 2009 at 09:16 AM.
[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
|