Jump to content
Xtreme .Net Talk

Squirm

Leaders
  • Posts

    186
  • Joined

  • Last visited

2 Followers

About Squirm

  • Birthday January 11

Personal Information

  • Occupation
    Student, Web Designer

Squirm's Achievements

Newbie

Newbie (1/14)

0

Reputation

  1. Yep, thats what I ended up doing. I installed .Net 2.0, but I'm still using VS.Net 2002 and the whole IEnumerator(Of Char) thing wasn't happening. I found an article (bing!) on MSDN and in Example 2 they used this explicit implementation technique which seems to work. public class StringEnumerator : IEnumerator { //Fields private IEnumerator innerenum; //Properties public string Current { get {return this.innerenum.Current.ToString();} } object IEnumerator.Current { get {return this.innerenum.Current;} } //Constructors public StringEnumerator(IEnumerator enumerator) { this.innerenum = enumerator; } //Public methods public bool MoveNext() { return this.innerenum.MoveNext(); } public void Reset() { this.innerenum.Reset(); } } Thanks very much.
  2. I noticed that the CharEnumerator class (which implements IEnumerator) is allowed to return a char value for the Current property. Similarly, MessageEnumerator.Current returns a Message object, MethodDataEnumerator.Current returns a MethodData object, and so forth... It seemed to me that the implementation of IEnumerator does not care about the return type of the Current property, since clearly those classes have twisted it to their own needs, and can still claim to implement IEnumerator. Fed up with constantly casting from collections I know to only contain strings, I thought of making my own little wrapper enumerator for string-only collections (although it would work with any object type, since it explicitly calls ToString() on every element): [code=csharp]public class StringEnumerator : IEnumerator { //Fields private IEnumerator innerenum; //Properties public string Current { get {return this.innerenum.Current.ToString();} } //Constructors public StringEnumerator(IEnumerator enumerator) { this.innerenum = enumerator; } //Public methods public bool MoveNext() { return this.innerenum.MoveNext(); } public void Reset() { this.innerenum.Reset(); } }[/code] Does this compile? As you can probably guess, the answer is no, it does not: Yeah, I've had that before, and half expected it. But how do these other classes break the rules? :confused:
  3. So I've written my XML schema. VS likes it, and the xsd tool creates nice serializable classes, so the schema must be ok. I have called my namespace urn:xmlns:toffee like so: <xs:schema id="Toffee" targetNamespace="urn:xmlns:toffee" elementFormDefault="qualified" xmlns="urn:xmlns:toffee" xmlns:xs="http://www.w3.org/2001/XMLSchema"> .... </xs:schema> Now I want to test the schema in Sample.xml, so I started with this: <?xml version="1.0" encoding="utf-8" ?> <userfile xmlns="urn:xmlns:toffee" xmlns:toffee="urn:xmlns:toffee" toffee:schemaLocation="Toffee.xsd"> .... </userfile> userfile is the document/root element defined in the schema, and the code generated by xsd reflects that. However, the code above causes the following error when I open the xml file in VS: Changing the xmlns attribute of the userfile tag to "Toffee.xsd" causes the XML file to load without error, but intellisense for the document is incorrect since Toffee.xsd is not a namespace, just a filename. Do I really have to use the name of the xsd file as the namespace name? Argh! Its frustrating. All I want to do is have a namespace called urn:xmlns:toffee defined in the schema Toffee.xsd and have it referenced in Sample.xml such that I dont have to prefix every tag with toffee: I've read and reread all the tutorials I could find on XML schemas, and I just don't get it. :confused: Thanks for reading.
  4. You need to add references to the DirectX DLLs you wish to use.
  5. Thanks for the response. I have a shakey system working, which is a start. Thanks for the tip about returning an array of typenames rather than actual Type objects. This is my probing code: public Type[] FindPlugins(string dir) { AppDomain querydom; PluginFinder finder; Type[] types; querydom = AppDomain.CreateDomain("PluginQueryDomain", new System.Security.Policy.Evidence(AppDomain.CurrentDomain.Evidence)); querydom.Load(Assembly.GetExecutingAssembly().GetName()); finder = (PluginFinder) querydom.CreateInstanceAndUnwrap( Assembly.GetExecutingAssembly().FullName, "BlueFish.Plugins.PluginFinder"); types = finder.FindPlugins(dir); AppDomain.Unload(querydom); return types; } (I will now convert that to use type strings). It was actually much simpler than I had expected, since as you point out the MarshalByRef class deals with all the nasties. I think I can see how to get it all working now, the major hurdle I have at the moment is my large (mis?)use of delegates to private methods, which apparently are not allowed across appdomains, so I'm going to have to rethink on that issue. Thankyou for the indepth reply. It's reassuring to know I'm not the only person to have dealt with this problem. :) [edit]Re: GC.Collect(), I never normally use it, I just threw it in to be sure that if assemblies could be automatically unloaded, they would be. And the answer is that they can't. :)[/edit]
  6. Greetings, My aim is to provide a "plugins" system for an application I am developing. Having worked with plugins in COM I already knew the basic concepts involved and divil's articles on the subject meant I was very quickly able to get a working plugins system working. Or so I thought... The problem came when I wanted to unload a plugin, and in such a way that the DLL which contains it would no longer be locked by the framework - to allow for recompilation (and subsequent reloading of the modified plugin). In the absence of an Assembly.Unload method I expected that as soon as no types from the assembly were still instantiated, and there were no more references to anything within the assembly (including the assembly itself), that it would be automatically unloaded. Suffice to say this is not the case. It would appear that once an assembly is loaded, it is loaded forever, until the AppDomain which contains it terminates. Consider the following code: foreach (FileInfo f in dlls) { Assembly dll = Assembly.LoadFrom(f.FullName); } GC.Collect(); This is what I have come down to, and even this code will keep the assemblies loaded. This is doubly annoying since this basic operation is required even to just query the assembly for type information, even if you later discover that it does not contain any useful types (ie plugins). My attention is therefore turned to the AppDomain class. It seems I could create a new AppDomain every time I want to query the assemblies, and upon unloading (ending? terminating?) the AppDomain the DLLs containing the assemblies should be unlocked. When a plugin is to be instantiated, it can be loaded into its own AppDomain and when finished with, unloading the AppDomain should free the plugin assembly. But just looking at the AppDomain class (which I have never looked at before) suggests this is a daunting task and will break a lot of my code, since it wont be so simple to just pass an object reference between the application AppDomain and the plugin AppDomain. So, a few questions (finally!). Can an individual assembly be dynamically unloaded in the same way it is loaded, if so how? If AppDomains are the way to go, what sorts of things should I be looking to change in the program - how do AppDomains interact? Has anybody else been in a similar situation, and if so how did you solve it if you did? On one hand I can't believe it would be so involved to create a plugins system, especially with the lightness of divil's tutorials and all other information I can find on the subject. On the other hand I can see why the framework might be so restrictive, but it sure is annoying. Regards Squirm [edit]Found this on MSDN: There is no way to unload an individual assembly without unloading all of the application domains that contain it. Even if the assembly goes out of scope, the actual assembly file will remain loaded until all application domains that contain it are unloaded :-\[/edit]
  7. Yes indeed the enumeration and the Create function need to be changed if we add a new class. Big deal. It isn't exactly a huge problem, 3 lines of code at the most. This is a small proportion compared to the amount of code which would go into writing the new class. Is it enough for someone who is confident and proficient in VB to learn a new language? Probably not. Does this make him/her a bad programmer? No. In addition, anyone who has properly planned the development of their application will know in advance all or most of the classes which will be needed within the enumeration so any modifications will be small. You can take it further. Lets say you want to use template classes or template functions. As far as I know, these are not supported in Delphi. Is it worth learning C++ for this? Probably not. This is a good comparison since the code savings of templates are comparable to those you are demonstrating above with this code factory idea, perhaps even greater. You choose the right tools for the job. 99% of VB programmers do fine without template classes and without type classes. Does this make them bad programmers? No it doesn't.
  8. Would this be it? '********************************* 'In a module Public Enum ProcessorType Processor_VB = 0 Processor_Delphi = 1 End Enum '********************************* 'Interface IProcessor Public Sub Process() End Sub '********************************* 'Class ProcessorVB Implements IProcessor Private Sub IProcessor_Process() MsgBox "VB sucks!!" End Sub '********************************* 'Class ProcessorDelphi Implements IProcessor Private Sub IProcessor_Process() MsgBox "Delphi rocks!!" End Sub '********************************* 'Class UniversalGenerator Friend Function Create(ProcType As ProcessorType) As IProcessor If (ProcType = Processor_VB) Then Set Create = New ProcessorVB ElseIf (ProcType = Processor_Delphi) Then Set Create = New ProcessorDelphi End If 'Could also invoke the .Process method directly if needed End Function
  9. An interesting example, which would indeed be cumbersome if at all possible in VB6. Far more important than the lack of a Type type/class is the lack of inheritance. Trivial is indeed the key term here, since although the structure or style of the program code may be impossible to replicate in VB, the actual functionality of it is not. Furthermore, it would be interesting to view a disassembly of your Delphi program after compilation. I would expect the instancing of a genereric 'Type' class just involved the use of a lookup table to select which class to instantiate (since all calls to this member can be resolved at compile time). If this were the case, replicating the functionality would be pretty easy with an enumeration or anything which could uniquely identify each class. I'm guessing the C# example would be more complex than that with much of the inner workings hidden away within the framework. How do you think VB/COM's CreateObject works? All classes implement a known interface (in this case IUnknown). Since VB does support interfaces, it would be possible to write a class factory object/function.
  10. Do you mean at compile time or runtime? If the former, then you can just add the CS file to your project.
  11. The J2SDK would be a start: http://java.sun.com/j2se/index.jsp
  12. It means one of your program's threads has exited. An exit code of 0 generally means it terminated gracefully. So in short, no, this is not usually a concern and is entirely normal.
  13. Windows Mobile is the OS which supercedes Windows CE. PocketPC 2002 can run both the 2002 and 2003 versions.
  14. You might want to check out http://www.winsupersite.com
  15. The second snippet looks like it should work. Can you elaborate on 'it doesn't work'?
×
×
  • Create New...