Ooh so it's out of your control, well that changes matters..
I don't see any solutions then, except a couple of really really dirty things.
You can, with reflection, extract the Target Object from a delegate object. You can then check whether it is a Window1 and whether it has closed yet.
You could also try to subscribe to the OnClosing of Window1 (through that Target Object) and when it's triggered delete all delegates which have Window1 as Target Object.
Before I waste time going down this road, is that going to solve the original issue (of Window1 closing and still having a listener)? It would seem that wrapping a delegate in a WeakReference should theoretically have the same effect, no?
I'm not really liking WeakEventManager to be honest with you. Seems like everybody has to implement the IWeakEventListener interface.
I'm just really curious why my previous idea didn't work... of storing the WeakReferences myself???
I'm not sure to be honest whether it will solve your problem. Every weak reference solution seems to have pros and cons. The event model employed by .NET is flawed in this regard and relies on consumers unsubscribing correctly.
Another option maybe to forget about events in the normal way and go back to generating old fashioned windows messages or something similar so interested parties can override WndProc and catch the event there - no direct subscription... Maybe not practical or possible in your situation, certainly not as elegant as events, but worth a thought?
For an item of hardware I have written a Shared library to make it easy to use the API for this hardware. The library sets up data structures and handles, buffers etc for simple program use.
For example to arrange data to be transmitted I call routings like:-
UINT16 TransmitData( UINT unit, UINT addr, TXBUFFER * tx_buffer );
However in VS2008 I used C++ in a MFC dialog application, which all worked well.
Having moved to VS2010, I now see that the intellisence does not work with this product.
So my thoughts were to use C# for the Windows forms and link in the Shared Library.
I have built the Shared Library in VS2010 so I need to understand how to access these function in a C# program. Is this using ‘Wrappers’ and how does the libraries API001.LIB and API001.h files link in?
For a C++ MFC program I included the headers and LIB files with the PATH set up for the DLL’s.
You can create a C++/CLI class library and include the .lib and .h there. Then create a managed class in C++ that wraps the functions. Finally, make a reference from the C# application to the C++/CLI project.
I always thought IDictionary checks key when adding elements by calling GetHashCode overrides - but I did a simple experiment, seems like it only call Equals (i.e. Even if two instances with same hash code added to a Hashtable or Dictionary, it won't blow up so long "Equals" return false)
I digged around MSDN[^] and found that "Override the Equals method whenever you implement the equality operator (==), and make them do the same thing. This allows infrastructure code such as Hashtable and ArrayList, which use the Equals method, to behave the same way as user code written using the equality operator."
So this confirms Hashtable or Dictionary uses only "Equals", not "GetHashCode" --- then what's "GetHashCode" for? Doesn't seems like "Hashtable" or "Dictionary<k,v>" are using it at all..?!?
The hashcode is only used balance the hash table.
What doesn't work is if A.GetHashCode() != B.GetHashCode() but A.Equals(B). That is, it may work accidentally but all bets are off.
That means that GetHashCode could return 0 and everything will still work. Performance will suffer though.
The key value is what is used for definining the functionality; the hash value is used for optimizing the performance.
IDictionary requires all keys to be different, that is all. Different keys may result in the same hash value, as the key can have any size, and a hash is just a 32-bit integer, so you can't have an infinite number of different hash values.
And please use PRE tags, I don't read unformatted code...
CORRECTION - Dictionary did throw an ArgumentException if insert two items (where "Equals" returned true) gets inserted into dictionary twice (just set "j" to a bigger number, say 2)
However, below I've tried to implement GetHashCode in two ways:
ATTEMP 1 (correct because "GetHashCode" aligned with "Equals") --- 46 seconds to recall the elements by Key
ATTEMP 2 (Incorrect because not aligned with implementation in "Equal") --- 49 seconds (Seems like negligible and diff really arise from the addition XOR operation in GetHashCode)
You can try to implement GetHashCode = a^b, it'd be done in no time.
I'm not really sure why we need "GetHashCode" still - (unconvinced that its uses it's primarily internal to Dictionary's internal retrieval and impact only speed)
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
namespace TestDictWithDuplKeys<br />
publicclass SomeClass<br />
publicint a = 0;<br />
publicint b = 0;<br />
publicint c = 0;<br />
publicint d = 0; // Not part of Primary key so excluded from "Equal"<br />
publicoverridebool Equals(object obj)<br />
SomeClass cObj = null;<br />
if (obj != null && obj is SomeClass)<br />
cObj = (SomeClass)obj;<br />
if (this.a == cObj.a && this.b == cObj.b && this.c == cObj.c)<br />
publicoverrideint GetHashCode()<br />
// NOTE: Even though ATTEMP 2 is "Wrong", I see only slight performance degradation (from 45 sec to 49 sec)<br />int HashCode = a ^ b ^ c; // ATTEMP 1: Correct! Because it's same as in "Equal"<br />// int HashCode = a ^ b ^ c ^ d; // ATTEMPT 2: GetHashCode should return same value for "Equal" instances - this means implementation should include "c" (same as in "Equal"!)<br />return HashCode;<br />
class Program<br />
staticvoid Main(string args)<br />
IDictionary<SomeClass, string> SomeDict = null;<br />
SomeClass o = null;<br />
constint MAXITEMS = 1000000;<br />
#region Add to dictionary, with duplicate keys!<br />
SomeDict = new Dictionary<SomeClass, string>(MAXITEMS);<br />
for (int j = 0; j < 1; j++)<br />
for (int i = 0; i < MAXITEMS; i++)<br />
o = new SomeClass();<br />
o.a = i;<br />
o.b = i * 2;<br />
o.c = i * 3;<br />
o.d = i * 4;<br />
SomeDict.Add(o, Guid.NewGuid().ToString());<br />
Console.WriteLine("Pass #" + j);<br />
Console.WriteLine("Finished adding elements to dict....");<br />
#region Retrieve from dictionary<br />
DateTime Start = DateTime.Now;<br />
foreach(KeyValuePair<SomeClass, string> Entry in SomeDict)<br />
string Value = SomeDict[Entry.Key];<br />
// Console.WriteLine(Value);<br />
DateTime End = DateTime.Now;<br />
Console.WriteLine("Duration(sec):" + End.Subtract(Start).TotalSeconds);<br />
catch (Exception Ex)<br />
If the application uses a database, it would be simple to add an address table with a column companyID that links to another table company. Then you could retrieve the address as and when you need it. It would be no good keeping it in a In-Memory structure such as DataSet / ArrayList as you would need to Hard Code the values in the code. A viable alternative is to persist the addresses using XML, if the application is not using a database. Obviously, this would depend on the application itself.
Hope this helps.
...and I have extensive experience writing computer code, including OIC, BTW, BRB, IMHO, LMAO, ROFL, TTYL.....
Where to place them is a tricky one. I'd narrow it down to XML or a database, that way they can be changed/added to with little effort (and used, for example, in word for mail-merge) and without needing a re-compile.
You might want to google "LINQ To SQL" or "Entity Framework" for two simple ways of getting the data out in a C# app. LINQ to SQL is probably easier for your requirements.
From your other comments my guess is that you don't have a database already.
So some sort of file is going to probably be the best solution.
After you have decided on a file then the format of the file could be XML. Or something else that you make up.
You could embedded them in the application itself as a resource or as code as well. This of course means that updating them requires updating the application. But there could even be business requirements to do that.