|
I understand where the scope of an object starts and ends, I just do not know the names of the base class handlers which are (or should be) called when either the OK or Cancel button is clicked.
I used Dispose(), not because I did not understand scope, but, because it was the only method (I know it is the WRONG one) I could find that at least removed the window, and broke out of the modal loop.
I also want to find out how it is all wired up.
In de SDK we had the WindowProc, in MFC we have the MessageMap to tie events to handlers, what do we have in C#.NET? A Click on a Button event gets somewhere attached to the handler for that event. how and where?
An event handler can decide to terminate the modal loop and thereby return from ShowDialog. (how? what base method does it call to accomplish this). In other words, in MFC we have 'EndDialog' to get out of the modal loop. What do we have in C#.NET to do this?
Thanks for your time and interest,
Regards,
Update- Stop Press,
Somewhere in Stackoverflow:
"but, I know that setting DialogResult closes the form! everyone knows that!".
Well, I did not know that! One of those surprises! It would take some gymnastics in MFC to do that! At the same time, I do not think that many MFC programmers would be happy about such development.
It is where thing are organised entirely differently than what an MFC programmer in his innocence would suspect. What also does not help that everything in C#.NET has an entirely different naming convention.
Anyway, I tried it.
this.DialogResult = DialogResult.Cancel;
Closed the Dialog, and left it available for further interrogation.
The other queery stil stands. this.Hide()( called in the LogOn button handlers) hides the entire application, and not just the LogOn dialog. Is this a feature of the debug mode, or an error on my part.
Thanks again;
Bram van Kampen
modified 17-May-13 19:27pm.
|
|
|
|
|
Bram van Kampen wrote: I used Dispose(), not because I did not understand scope, but, because it was the only method (I know it is the WRONG one) I could find that at least removed the window, and broke out of the modal loop. Yes, totally wrong; you should have a button on the form that returns a DialogResult . If you click on a button on your form and look at the properties you'll see how you can set it to return OK , Cancel etc. This will then perform graceful closure of the form and return to your code.
Bram van Kampen wrote: The other queery stil stands. this.Hide()( called in the LogOn button handlers) hides the entire application, and not just the LogOn dialog. Is this a feature of the debug mode, or an error on my part. Not sure about this, I would need to run some more tests; if time allows I'll give it a try some time over the weekend.
[edit]One thing I would suggest is that you clear MFC from your mind. MFC and .NET may look similar but there are many subtle differences which can catch you out. There are plenty of beginner articles around, I found them very useful when I first started with C#.[/edit]
Use the best guess
|
|
|
|
|
I did have a bunch of similar public methods for converting an RGB structure to grey scale but decided it made the class too complicated so I changed them to private and created an Enum which was used as a parameter for a public method which then called those private methods method using switch.
One of the private methods then developed a need for a parameter, but only one of them. I made the parameter optional but then stumbled into the problem of public shared methods not being considered as constants, so I switched to overloading for this method and wanted to add an optional Enum to represent the two variants of that one method, this smelt bad. So I thought to use overloading again, but the second version of the method would still be able to accept all the options of the first Enum, even though only one was relevant, the one that needed the second Enum, still smelt bad.
I'm struggling to follow this explanation myself, so if code helps then here it is (simplified). I don't like it.
I could possibly use the second ToGreyScale method with just the LumaEnum parameter but that, to my mind, makes the use of the class problematic since it's not intuitive. Calling the second method GreyScalebyLuminosity makes a nonsense of trying to get rid of all those differently named GreyScale methods.
Is there a pattern I can use here? Or just a better design than this?
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod)
Select Case method
Case RGBGreyScaleMethod.Average
Me.GreyScaleByAverage()
Case RGBGreyScaleMethod.BlueChannel
Me.GreyScaleFromBlue()
Case RGBGreyScaleMethod.Decompose
Me.Decompose()
Case RGBGreyScaleMethod.Luminosity
Me.GreyScaleByLuminosity()
Case Else
Throw New ArgumentOutOfRangeException()
End Select
End Sub
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod, ByVal factors as LumaEnum)
Select Case method
Case RGBGreyScaleMethod.Luminosity
Select Case factors
Case LumaEnum.BT709
Me.GreyScaleByLuminosity(LumaFactors.BT709)
Case LumaEnum.BT601
Me.GreyScaleByLuminosity(LumaFactors.BT601)
Case LumaEnum.GIMP
Me.GreyScaleByLuminosity(LumaFactors.GIMP)
Case Else
Throw New ArgumentOutOfRangeException()
End Select
Case Else
Throw New ArgumentOutOfRangeException()
End Select
End Sub
Private Overloads Sub GreyScaleByLuminosity()
Me.GreyScaleByLuminosity(LumaFactors.BT709)
End Sub
Private Overloads Sub GreyScaleByLuminosity(ByVal factors As LumaFactors)
Dim c As Double = Me.Luminosity(factors)
Me._Red = CInt(c)
Me._Green = CInt(c)
Me._Blue = CInt(c)
End Sub
Public Enum LumaEnum
BT709
BT601
GIMP
End Enum
Public Enum
Average
BlueChannel
Decompose
Luminosity
Desaturate
Lightness
RedChannel
GreenChannel
End Enum
|
|
|
|
|
Mike-MadBadger wrote: I'm struggling to follow this explanation myself I tried twice, and got lost twice. Let's try it differently; you've seen how the different events in .NET all look similar, with two parameters? One could do something similar;
Public Class MyParamaterBase
Public Property Id As Guid
End Class
Public Class MyExtendedParameter
Public Property Title as String
End Class
Public Class SomeConsumingClass
Public Sub SomeMethod(TheParameter As MyParameterBase)
If TheParameter is MyExtendedParameter Then
Console.WriteLine((TheParameter as MyExtendedParameter).Title)
EndIf
End Sub
End Class
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Ok, so instead of an Enum parameter I have a base class parameter which through polymorphism can take a derived type which carries the extra parameter information?
I guess I could do the same thing by using an interface as the parameter?
Thanks,
Mike
|
|
|
|
|
Mike-MadBadger wrote: I guess I could do the same thing by using an interface as the parameter? Yes
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I think this is simply a variation on your suggestion (in effect), using a nested class.
Public Class Class1
Private _param As Double
Public Sub New(ByVal amount As Double)
Me._param = amount
End Sub
Public Property Param() As Double
Get
Return Me._param
End Get
Set(value As Double)
If Not value = Me._param Then
Me._param = value
End If
End Set
End Property
Public Function ToGrey() As ToGreyMethods
Return New ToGreyMethods(Me)
End Function
Public Class ToGreyMethods
Private _outer As Class1
Public Sub New(ByRef outer As Class1)
Me._outer = outer
End Sub
Public Sub Increase(ByVal amount As Double)
Me._outer.Param += amount
End Sub
Public Sub Decrease(ByVal amount As Double)
Me._outer.Param -= amount
End Sub
End Class
End Class
Module Module1
Sub Main()
Dim thing As Class1 = New Class1(10)
thing.ToGrey.Increase(5)
Console.WriteLine(thing.Param.ToString())
thing.ToGrey.Decrease(10)
Console.WriteLine(thing.Param.ToString())
Console.ReadKey()
End Sub
End Module
My only problem with this is that I can't seem to hide the nested class so one could be created at runtime manually rather than as a result of a call to ToGrey(), which starts to feel a bit messy or at least has the potential to get messy since I do.t know what would happen if, for example, you could do this.
Public Sub Example()
Dim thing as Class1 = New Class1(10)
Dim whoops as ToGreyMethods = thing.ToGrey()
End Sub
|
|
|
|
|
Mike-MadBadger wrote:
The effect would also be there without the new object; any object that's embedded in a property can be put in a variable, and one can manipulate the referenced object without looking at whose property it was.
Public Class Class1
Private _param As Double
Private _methods As ToGreyMethods
Public Sub New(ByVal amount As Double)
Me._param = amount
Me._methods = New ToGreyMethods(Me)
End Sub
Public Property Param() As Double
Get
Return Me._param
End Get
Set(ByVal value As Double)
If Not value = Me._param Then
Me._param = value
End If
End Set
End Property
Public ReadOnly Property ToGrey() As ToGreyMethods
Get
Return _methods
End Get
End Property
Public Class ToGreyMethods
Private _outer As Class1
Public Sub New(ByRef outer As Class1)
Me._outer = outer
End Sub
Public Sub Increase(ByVal amount As Double)
Me._outer.Param += amount
End Sub
Public Sub Decrease(ByVal amount As Double)
Me._outer.Param -= amount
End Sub
End Class
End Class
Module Module1
Sub Main()
Dim thing As Class1 = New Class1(10)
thing.ToGrey.Increase(5)
Console.WriteLine(thing.Param.ToString())
thing.ToGrey.Decrease(10)
Console.WriteLine(thing.Param.ToString())
Dim whoops As Class1.ToGreyMethods = thing.ToGrey()
Console.ReadKey()
End Sub
End Module
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
BTW, I'd give a +5 but there's no option to do so
|
|
|
|
|
<- It's hidden
|
|
|
|
|
Use a definition object. That is passed to the second object and defines how it runs. The definition object can provide things like a default definition, common definitions, common ways to create definitions and custom definitions.
|
|
|
|
|
Unfortunately I'm not sure exactly what a definition object is and Google hasn't helped, could you possibly help me with a link or a bit more explanation?
|
|
|
|
|
pseudo code
pre>
Object Def
ByVal method As RGBGreyScaleMethod;
ByVal factors as LumaEnum;
...
Object Implem
Doit(Def def)
|
|
|
|
|
It looks like you found a solution that you are happy with, but I thought that I would throw my 2 cents worth into the fray.
Based on my understanding of your code, the Luminosity method is the only one that needs a second parameter. Why not remove Luminosity from your methods enum and change:
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod, ByVal factors as LumaEnum)
to:
Public Overloads Sub ToGreyScale(ByVal factors as LumaEnum)
I think that this would given you the intuitiveness factor that you are seeking.
As I don't know what it all is that you are doing in this "Class" the following may not be relevant, but I will throw it out as an alternative. It appears that all you are using it for is to convert a Color structure to its equivalent greyscale color. Perhaps, this may be a case for using extension methods to the Color Structure.
Module GreyScaleExtentions
Public Enum RBGMethods
Average
BlueChannel
Decompose
Desaturate
Lightness
RedChannel
GreenChannel
End Enum
Public Enum LumaEnum
BT709
BT601
GIMP
End Enum
''' <summary>
''' Converts Color to greyscale equivalent using RGBGreyScaleMethod
''' </summary>
''' <param name="c"></param>
''' <param name="RGBMethod"></param>
''' <returns></returns>
''' <remarks></remarks>
<Runtime.CompilerServices.Extension()> _
Public Function ToGreyScale(ByVal c As Color, ByVal RGBMethod As RBGMethods) As Color
End Function
''' <summary>
''' Converts Color to greyscale equivalent using luminosity method
''' </summary>
''' <param name="c"></param>
''' <param name="factors"></param>
''' <returns></returns>
''' <remarks></remarks>
<Runtime.CompilerServices.Extension()> _
Public Function ToGreyScale(ByVal c As Color, ByVal factors As LumaEnum) As Color
End Function
End Module
Then you could use like this:
Sub test()
Dim c As Color = Color.FromArgb(230, 134, 231, 10)
Dim gs As Color
gs = c.ToGreyScale(LumaEnum.BT601)
gs = c.ToGreyScale(RBGMethods.Average)
End Sub
|
|
|
|
|
That one had occured but it meant that a user of the class would need to know that the overload without a method would give ByLuminosity, which was the bit that felt unintuitive.
BTW, thanks for the <Runtime.CompilerServices.Extension()> piece, I assume that's how extension methods work?
I might add those to extend the Color type to include the functionality in my RGB and aRGB types, thanks.
|
|
|
|
|
Quote: That one had occured but it meant that a user of the class would need to know that the overload without a method would give ByLuminosity, which was the bit that felt unintuitive.
The issue of being intuitive is very subjective. I see the intuitive part being to use the "ToGreyScale" method and even that may require some explanation. At some point a programmer has to demonstrate some competence and look at the provided documentation. This is the reason that I showed the visual studio intellisense support using xml comments in the code I posted (see: Documenting Your Code With XML Comments). Providing this documentation is your responsibility as the developer and you should not be relying on something being intuitive as a substitute for proper documentation. Paste the extension method code I provided into a project and observe the intellisence pop-ups when you try to use the defined methods.
Quote: BTW, thanks for the piece, I assume that's how extension methods work?
Assume nothing when coding. Use your friendly search engine and research it yourself. I have found that this general query works well in the major search engines:
msdn TopicYouWant -social"
The reason for the "-social" is to try to eliminate results from the msdn help forums and to focus on the documentation pages.
So much for my preaching for the day, have a good weekend.
|
|
|
|
|
Thank you. My code is XML commented I just left it out of the simplified examples here. For the extension methods I'm not sure why I left the question in, I had searched Google, guess I was just looking for confirmation - probably not necessary.
On the structure, I agree but something feels clunky, nevermind.
Have a nice weekend
|
|
|
|
|
I have an DLL assembly that is used by many other apps. This assembly is likely to change as new requirements are discovered.
Now, let's say the referencing apps are all running, I change the code in the dll for a new app, and then start the new app.
What I'm seeing is that the new app uses the version of the assembly that's already in memory. Is that an accurate statement?
If so, is there a way to force the new app to use the copy of the dll that it was linked to instead of using what's already in memory?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997
|
|
|
|
|
The running application (or new application using currently cached DLL) doesn't know about changes to the DLL itself in most cases, so you'd have to write some kind of polling thing, or event response to the Windows file changed event, and pick up the new DLL and link it in "manually" like this...
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
Type type = assembly.GetType("MyType");
object instanceOfMyType = Activator.CreateInstance(type);
This is frustrating for sure, when you have lots of apps using the same DLLs - I've had this issue with multiple web sites before, and it took us a long time to understand what was happening. You would think that copying over the old DLL would cause a system-wide "this DLL is no longer up to date" kind of event, but apparently not.
|
|
|
|
|
I tried using strong naming, but that had no effect.
WTF good is code re-use if I can't actually re-use the freakin code in compiled form?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997
|
|
|
|
|
Yeah it's not ideal. Sometimes you have to re-start the server. I think they opted for making it harder to use the wrong assembly instead of easier to manipulate which ones are used.
|
|
|
|
|
John Simmons / outlaw programmer wrote: ...by many other apps.
What do you mean by "app"? Or more specifically how many process spaces are you running into which these apps appear?
An executable/service has a load dynamic that, excluding GAC, will load based on several factors but the primary one is the current working directory of the primary executable. A new process space will load a new copy of the dll that it found doing an assembly search. It doesn't have anything to do with what other processes have loaded into memory.
Now if you are messing with AppDomains and changing the loading semantics then that alters how it searches and that would alter where it looked. The process would still load a new copy though.
John Simmons / outlaw programmer wrote: What I'm seeing is that the new app uses the version of the assembly that's
already in memory. Is that an accurate statement?
Not in general, but as noted it depends on what you mean by "app". The process (AppDomain) loads the dll into memory. It won't load it again, but every process gets one (I can't remember if there is AppDomain chaining or not.)
|
|
|
|
|
Sure that's what should happen, but I've seen a DLL basically get "locked" on the whole machine, and even though we replaced the DLL itself, the old behavior continued until we shut down the web server. This was on a web site where several sites used the same ORM assembly, and it appeared that IIS was loading one copy of the DLL for everybody, and it refused to let go of that even when the underlying file was DELETED. We had different app pools for each site, so it was really unexpected. I would have thought it was impossible, actually.
Pretty sure that's what he's talking about happening, and I agree it shouldn't happen, particularly when he said he starts a new copy of the app. It completely baffled me and a few guys in India - we couldn't figure out what was going on, and after that night(!) it became standard procedure to re-start the web server after rebuilding the ORM assemblies.
|
|
|
|
|
Jasmine2501 wrote: and it appeared that IIS was loading one copy of the DLL for everybody, and it
refused to let go of that even when the underlying file was DELETED
IIS is a process. It (presumably) uses AppDomains but that goes back to whether chaining is involved.
And per the docs chaining can happen at least with the default AppDomain.
And of course if chaining is involved then deleting the dll would have no impact - if .Net finds the assembly in memory (within the Process/AppDomain context) then it doesn't load it again.
|
|
|
|
|
If you want to keep both the new and the old dlls, you can use something called a Publisher Policy.
This would allow you to use the new dll. If you want to use the old one just set the publisher policy setting off.
More here[^].
|
|
|
|
|