Laden...

Forenbeiträge von Kabelsalat Ingesamt 369 Beiträge

27.04.2007 - 22:23 Uhr

Genauer geht nicht, da bisher nur das Design des Logging-Parts detaillierter ist:

27.04.2007 - 21:54 Uhr

Guten Abend,

Ich arbeite Gerade am Design einiger Klassen, von denen einige erweiterte Logging-Funktionalität zur Verfügung stellen, wohingegen der Rest Teil eines Konfigurationsframeworks ist.

Nun möchte ich jedoch aus dem Konfigurationsframework heraus die Logging-Klassen nutzen. Soweit kein Problem, allerdings soll die Laufzeit-Konfiguration der Logging-Funktionen über das Konfigurationsframework erledigt werden - wegen der zirkulären Referenzen ist an eine direkte Umsetzung also nicht zu denken.

Bisher ist mir leider kein Ausweg in den Sinn gekommen (außer bei der Implementierung des Konfigurationsframeworks auf Logging zu verzichten). Wie würdet ihr das Problem angehen?

Grüße vom Bodensee

Kabelsalat

27.04.2007 - 21:42 Uhr

Vor einiger Zeit habe ich einen Formelparser geschrieben, der beliebige Formeln analysiert und intern als "Umgekehrte Polnische Notation" (UPN) darstellt (Vielleicht besser bekannt als Infix-Notation oder "Reverse Polish Notation" - RPN). Die Speicherung erfolgt natürlich nicht als Abfolge von Zeichen oder Strings, sondern der Term wird in "Tokens" zerlegt. Das sind Klassen bzw. Unterklassen, die etwa bei Operatoren auch gleich deren Implementierung umfassen - verzichtet habe ich allerdings auf die Vereinfachung der Terme.

... herunterladen kannst du die Borland Package Library (BPL) einschließlich Beispielanwendung hier: http://www.epifiles.de/daten/index.php?N=A&dir=epiSource%2FDelphi%2FMathExpression

Wie du vielleicht schon am Begriff BPL gemerkt hast, handelt es sich jedoch nicht um .Net sondern um Delphi (war damals für den Schulunterricht) - vielleicht hilft es dir dennoch weiter.

Die Zip-Datei enthalt drei Ordner:

  1. MathExpression: Die BPL ("Klassenbibliothek"), welche die eigentliche Funktion zur Verfügung stellt. Für dich interessant sind vor allem die Quellcode-Dateien MathExpression.pas und Tokens.pas

  2. MathExpressionBPLSample: Beispielanwendung, die auf obige BPL aufbaut.

  3. MathExpressionSample: Wie MathExpressionBPLSample, allerdings wird die Funktionalität der BPL direkt eingebunden.

Die Dokumentation kann ich leider nicht mehr finden, vielleicht habe ich auch nie eine geschrieben.

PS: Ich halte einen eigenständigen Parser für die bessere Lösung. Der zuvor verlinkte Artikel (http://www.codeproject.com/cs/algorithms/matheval.asp) beschreibt zwar eine sehr simple wie auch elegante Lösung, die bei falscher Umsetzung allerdings schwerwiegende Sicherheitslücken schafft.

17.12.2006 - 23:04 Uhr

Original von MagicAndre1981

Original von BerndFfm
Wo kann man nun sehen was alles geändert ist ?

Grüße Bernd

schau mal hier:


>

Diesen pseudo-deutschen Kauderweltsch kann doch keiner verstehen... hier die englische Sprachversion: http://support.microsoft.com/kb/928957/en-us

10.12.2006 - 20:07 Uhr

Das ganze ist keine Anwendung die zu einem bestimmten Stichtag fertig sein muss, sondern ein Hobbyprojekt, bei dem es mir um den Lerneffekt und damit auch um die bestmögliche Implementierung geht (auch wenn diese in Anbetracht der Entwicklungszeit völlig unökonomisch sein sollte)... soviel zum Grund des Trubels.

10.12.2006 - 18:32 Uhr

Dieses Thema gewinnt für mich nun wieder an Prisanz, daher habe ich mich auch erneut mit meinem Feedback an Microsoft (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=217331) auseinandergesetzt.

Abgesehen davon, dass ich die Aussage dieses Scott nicht nachvollziehen kann (wie auch in meinem Kommentar dargestellt), verstehe ich auch seine Workaround-Vorschläge nicht: SafeHandles sind zwar wirklich eine nette Sache, aber die Icon.FromHandle-Methode nimmt nunmal nur einen IntPtr Wert entgegen und auch der vorgeschlagene Icon-Wrapper wird wohl kaum nützlich sein, da alle .Net Klassen eben auf der Icon-Klasse aufbauen...

... könnt ihr mir sagen, wo mein Denkfehler liegt?

08.12.2006 - 21:20 Uhr

Und genau mit Reflection gehen auch dynamische Variablenbezeichner: System.Reflection.Emit ist die Lösung - einfach zur Laufzeit eine entsprechende Assembly erstellen und ausführen 😉 ... Am Beispiel TypeMock.Net sieht man, dass es unter gewissen Sicherheitstechnischen Voraussetzungen auch möglich ist bestehenden Code zur Laufzeit zu substituieren, also auch in dieser Hinsicht sind Möglichkeiten gegeben. Funktioniert aber eben nur durch die dynamische Ausführung des ganzen - die Vorteile einer statischen Übersetzung sind dahin und überdies gelten die Kritikpunkte meiner Vorposter.

07.12.2006 - 18:47 Uhr

Wahrscheinlich hängt das Phänomen mit der Speicherfragmentierung zusammen: Die .Net Runtim kann einfach nicht genügend zusammenhängenden Speicher reservieren, damit es passt...

07.12.2006 - 14:07 Uhr

Deswegen schrieb ich, dass sich an der machine.config evtl. noch etwas drehen lässt - wahrscheinlich aber eher nicht...

06.12.2006 - 18:41 Uhr

Mit Visual Studio hat das auf keinen Fall etwas zu tun - wenn dann musst du schon die machine.config anpassen, aber dass sich darin eine Lösung des Problems verbirgt, unwahrscheinlich.

Vielleicht solltest du lieber versuchen, mit weniger Speicherbedarf auszukommen und Teile auf die Festplatte auszulagern...

... ansonsten könnte der Wechsel auf ein 64Bit-System die Lösung deiner Probleme sein: Eigentlich sollte auch .Net auf einem solchen System mehr als 4GB verwenden können und auch diese magische 2GB Hürde sollte demnach nicht mehr existieren!

06.12.2006 - 15:51 Uhr

Wäre super, wenn du zusammen mit neuen Versionen ein Changelog veröffentlichen würdest. Momentan kann man sich nämlich nicht sicher sein, welche Verbesserungen vorgenommen wurden - im Speziellen geht es um folgendes:

Original von Kabelsalat
Vielleicht kannst du den TODO-Manager noch dazu bewegen mit Projektmappenordnern klar zu kommen:

Bei Projekten, die sich in einem Projektmappenverzeichnis befinden, fehlt der Kontextmenü Eintrag:

Erwartet:

Ansonsten ein super Tool. Danke 👍

Dem Screenshot auf deiner HP zu Folge scheint es allerdings mit der neuen Version korrekt zu funktionieren:

http://www.genne-develop.com/images/vs_addin.png

Nochmal Danke für das tolle AddIN!

05.12.2006 - 21:32 Uhr

"Die Kultur ist eine Eigenschaft des gerade ausgeführten Threads. Diese schreibgeschützte Eigenschaft gibt Thread.CurrentCulture zurück. Beim Starten eines Threads wird seine Kultur am Anfang mithilfe von GetUserDefaultLCID aus der Windows-API bestimmt." (Dokumentation zu CultureInfo.CurrentCulture)

... war auch schon unter .Net 1 so!

05.12.2006 - 18:02 Uhr

Das hat eigentlich nichts mit der Sprachversion des Frameworks sondern vielmehr mit den Betriebsystemeinstellungen zu tun...

05.12.2006 - 17:00 Uhr

Deine Beobachtung stimmt schon, da der Operator rechtsassoziativ ist...

04.12.2006 - 19:41 Uhr

Mit .Net alleine kommst du in dieser Situation nicht weiter, die WinAPI ist aber ganz hilfreich. Damit kannst du etwa an eine Windows-Formsanwendung nachträglich ein Konsolenfenster "anhängen" und auch wieder entfernen. Weitere Informationen findest du im Windows SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=7614FE22-8A64-4DFB-AA0C-DB53035F40A0&displaylang=en).

Damit sind u.a. folgende Konstellationen Möglich:

  1. Du übersetzt als Konsolenanwendung, gibst die Konsole bei fehlendem -v Argument aber wieder frei (sie wird nun beendet, wenn sie von keinem anderen Thread verwendet wird, ansonsten bleibt sie offen, kann aber aus dem aktuellen Prozess heraus nicht mehr angesprochen werden)

  2. Du übersetzt als Windowsanwendung und erstellst bei bedarf eine neue Konsole (Irgendwie doof, wenn die Anwendung aus der Konsole heraus gestartet wird, da dann eine neue geöffnet wird).

  3. Du übersetzt als Windowsanwendung, erkennst aber wenn diese von der Konsole gestartet wurde und hängst die Anwendung dann an die bestehende Konsole an.

Letzteres ist mit Sicherheit die eleganteste Lösung, allerdings kann ich dir dafür keine fertige Lösung bieten (möglich ist es aber). Wie bereits geschrieben, wird dir das Windows SDK mit Sicherheit weiterhelfen - such einfach nach AttachConsole, AllocConsole und FreeConsole...

02.12.2006 - 19:12 Uhr

Genau 🙂

02.12.2006 - 18:11 Uhr

Du kannst neben dem IIS sowie Apache mit Mono auch den Asp.Net Development Server nutzen. Ich würde dir sogar letzteres empfehlen, da du damit keine Sicherheitslücken schaffst (bloß lokal ansprechbar) - enthalten ist er im .Net Framework Redistributable und du findest ihn unter C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\WebDev.WebServer.EXE. Der Server kann standardmäßig nicht als Dienst eingerichtet werden, was in meinen Augen jedoch nicht unbedingt ein Nachteil ist: Benötigt wird der Server in vielen derartigen Umgebungen bloß selten und daher lässt er sich auch gut über einen Link im Startmenü oder auf dem Desktop starten (alternativ auch durch den Autostartordner).

Darüberhinaus existiert auch mindestens ein Projekt, das wie der Asp.Net Development Server einen simplen Asp.Net Host implementiert (das Meiste steckt bereits im Framework), die Webanwendung jedoch nicht im (lokalen) Netzwerk zur Verfügung stellt, sondern im integrierten Browser anzeigt. Gestartet wird die Anwendung mittels einer Dateitypverknüpfung mit der Endung .aspx (man macht einfach einen Doppelklick auf die entsprechende Datei). Den Link zum Projekt finde ich allerdings auf die Schnelle nicht mehr...

/edit:

Ich finde dummerweise bloß noch diesen Link: http://radio.weblogs.com/0105476/stories/2002/07/12/executingAspxPagesWithoutAWebServer.html

Zufällig bin ich vor kurzem jedoch auch auf eine fertige + funktionierende Anwendung gestoßen, die genau diesen Gedanken umsetzt (.Net 2), ich finde das Projekt bloß partout nicht wieder. Vielleicht hast du ja mehr Glück... wenn deine Suche erfolgreich sein sollte, lass es mich wissen!

/edit2:

Ich gebe die Suche jetzt auf, bin mir aber ganz sicher, dass derartiges bereits existiert. Zur Not müsstest du eine entsprechende Anwendung selber schreiben - auch das ist kein Hexenwerk. Weitergehende Informationen (bezogen auf .Net 1; sollten sich aber übertragen lassen) findest du hier:

http://www.microsoft.com/belux/msdn/nl/community/columns/desmet/hostaspnet1.mspx
http://www.fawcette.com/vsm/2002_10/magazine/columns/aspnet/
http://aspalliance.com/articleViewer.aspx?aId=220&pId=
http://msdn.microsoft.com/msdnmag/issues/03/01/CuttingEdge/default.aspx

01.12.2006 - 14:56 Uhr

... und es gibt bereits im jetztigen .Net-Framework ein HashSet. Werft mal einen Blick in die Assembly vjslib.dll (J# Redistributable muss installiert sein) - dank .Net lässt sich diese Klasse natürlich auch wunderbar von C# aus nutzen.

01.12.2006 - 13:40 Uhr

wie Kabelsalat schon oben geschrieben hat, wegen der Zugriffszeit. Man müsste die Objekte auch nicht doppelt hineinschreiben. In
>
verwende ich z.B. einen konstanten Wert (true) vom Typ bool als Value. In dem Link findest du auch beschrieben, warum es sinnvoll sein kann, die Objekte im Key und nicht im Value einzutragen.

Vom Speicherbedarf sollte es jedoch keinen Unterschied machen, ob ich Dictionary<MyType, MyType>, Dictionary<MyType, bool> oder Dictionary<MyType, int> verwende (es sei den MyType ist ein Wertetyp). Wie in deinem Artikel beschrieben, kann unter anderen Bedingungen, jedoch ein anderer Wert nützlich sein...

@FZelle: Danke für den Hinweis!

30.11.2006 - 22:51 Uhr

Mmh... in welchem Verhältnis steht eigentlich der Speicherbedarf des Dictionaries im Vergleich zur List?

30.11.2006 - 22:48 Uhr

Folgende Einführungen - besonders aber die erste - werden dir mit Sicherheit weiterhelfen:

http://www.yoda.arachsys.com/csharp/threads/
http://www.albahari.com/threading/

30.11.2006 - 22:39 Uhr

Hallo,

Ich bräuchte eine Collection, bei der sich möglichst flink feststellen lässt, ob ein bestimmtes Objekt enthalten ist oder nicht. List<MyType>.Contains ist eine O(n) Operation, mit Dictionary<MyType, MyType> müsste sich jedoch annähernd O(1) erreichen lassen - was ist jedoch der Nachteil von


Dictionary<MyType, MyType> myDictionary = new Dictionary<MyType, MyType>();

myDictionary.Add(myObj1, myObj1);
myDictionary.Add(myObj2, myObj2);
myDictionary.Add(myObj3, myObj3);

// ~O(1)
bool containsObj3 = myDictionary.ContainsKey(myObj3);

gegenüber


List<MyType> myList = new List<MyType>();

myList.Add(myObj1);
myList.Add(myObj2);
myList.Add(myObj3);

// O(n)
bool containsObj3 = myList.Contains(myObj3);

Wären SortedList bzw. SortedDictionary eine gute Alternative? Wie würdet ihr das Ganze angehen?

Danke für eure Hinweise

Kabelsalat

30.11.2006 - 15:48 Uhr

Diese sollten aber bloß sehr sehr selten vorkommen, da bereits FXCop bzw. die CodeAnalysis-Komponente aus dem Visual Studio Team System dies kritisiert.

30.11.2006 - 15:45 Uhr

Original von Golo
Dass das nicht geht, wusste ich noch nicht ...

Theoretisch müsste es bei einem reinen Setter gehen (probiert habe ich es aber noch nie) - in Kombination mit einem Getter kann es aber nicht funktionieren: Wenn man sich eine generierte Assembly mit Reflector anschaut (oder den J# Code in der Doku) sieht man, dass intern folgendes generiert wird:


public void set_ShadowCopyFiles(string value)
{
     // ...
}

public string get_ShadowCopyFiles()
{
     // ...
}

Nun darf beim Überladen einer Methode der Rückgabewert nicht geändert werden und daher kann get_ShadowCopyFiles() nicht mit einer alternativen Funktion mit Rückgabewert bool überladen werden.

Alternativ kann man auch folgendermaßen argumentieren:


// Angenommen folgendes ginge...
public string ShadowCopyFiles { get; set; }
public bool ShadowCopyFiles { get; set; }

// ... würde folgendes noch funktionieren
ShadowCopyFiles = "NurEinTest";
ShadowCopyFiles = true;

// ... nun gibt es aber Konflikte (bzw. wenn es ginge würde es sich um schlechtes Sprachdesign handeln, da der Compilerbau unnötig erschwert würde)
string testString = ShadowCopyFiles;
bool testBool = ShadowCopyFiles;

30.11.2006 - 14:50 Uhr

// Geht bekanntermaßen nicht
public string ShadowCopyFiles { get; set; }
public bool ShadowCopyFiles { get; set; }

Einzige Lösung wäre eine zweite Eigenschaft mit anderem Namen (und die bestehende als obsolete kennzeichnen) - saubere Lösung, naja!?

30.11.2006 - 14:20 Uhr

Auch bei Microsoft arbeiten nur Menschen... genauso wirst du in jedem anderen Großprojekt (etwa auch Java) Mist finden. Aus Gründen der Abwärtskompatibilität lässt sich die von dir genannte Eigenschaft leider auch nicht ändern.

25.11.2006 - 23:30 Uhr

Selected.PositionX ist aber nicht vom Typ Point (vom Namen her ziemlich unwahrscheinlich, da ich sonst von Selected.Postion.X ausgegangen wäre).

25.11.2006 - 16:32 Uhr

Mit 99,9%er Wahrscheinlichkeit handelt es sich bei Selected.PositionX um ein Property, dessen Setter den zugewiesenen Wert nicht übernimmt. Dies kann an einer fehlerhaften Implementierung liegen, könnte aber auch Absicht des Entwicklers sein. Näheres solltest du der Dokumenation der zugehörigen Klassen entnehmen können. Sofern du der Entwickler dieser Klasse bist, hast du den Setter nicht richtig implementiert...

... könnte allerdings auch am Getter liegen (wiederum gilt, dass es nicht zwangsläufig ein Fehler sein muss).

22.11.2006 - 23:15 Uhr

Möglichkeiten wären Snippets (-> Google) oder einfacher ein Template in der Toolbox. In beiden Fällen ist aber noch ein wenig Interaktion notwendig: Bei der ersten Variante muss man das Snippet einfügen und bei der zweiten das Template in die Datei ziehen. Vollautomatisch geht es mit Makros, aber ein entsprechendes müsstest du ersteinmal schreiben - wäre doch auch mal eine interessante Aufgabe für den Info-Unterricht!

21.11.2006 - 22:31 Uhr

Nichts ist unmöglich:

-> .NETZ geht einen ähnlichen Weg: http://www.madebits.com/netz/help.php#single
-> Der NAR Loader ist auch nicht schlecht: http://www.min.at/nar/
-> Und zum Schluss noch kommerziell: http://www.xenocode.com/Products/Postbuild/?Mid1

19.11.2006 - 15:15 Uhr

Müsste sich im Standardwert von Thread.CurrentUICulture und CultureInfo.CurrentUICulture wiederspiegeln!

19.11.2006 - 10:58 Uhr

So kannst du einstellen, ob automatisch das letzte funktionierende Kompilat verwendet wird: Letzte lauffähige Version ausführen (o.ä.) deaktivieren.

12.10.2006 - 21:44 Uhr

Stand übrigens auch bereits in dem von dir verlinkten Thread 😉

11.10.2006 - 22:40 Uhr

.Net verhällt sich schon richtig: System.UInt32 ist nicht CLS-Konform und daher wird ein System.Int32-Wert erwartet. Beides sind 32bit Werte und sie können daher exakt die selben (Bit-)Werte aufnehmen - der Unterschied liegt nur in der Interpretation eben dieser. Ein DWORD ist nichts anders als ein unsigned int, was dem zu Folge auch bedeutet, dass z.B. -1 auch als UInt32.MaxValue interpretiert wird. Die passenden Integer-Werte erhälst du mittels unchecked((int)4031775092) [natürlich mit entsprechendem Wert].

11.10.2006 - 18:25 Uhr

Was meinst du mit kommerziell? Dass es kommerziell verwendet werden darf, oder dass ein Unternehmen mit Gewinnabsicht dahinter steht? ... beides kann mit ja beantwortet werden ...

11.10.2006 - 15:27 Uhr

Sehr gut ist der PushOK Subversion SCP-Plugin für Visual Studio: Im Gegensatz zu AnkhSVN lässt es einen vorallem die eingebauten Versionalisierungsfeatures nutzen (wie bei SourceSafe).

10.10.2006 - 14:03 Uhr

Der Internetauftritt des Informatikjahres bzw. folgender Artikel hilft dir mit Sicherheit weiter: http://www-i1.informatik.rwth-aachen.de/~algorithmus/algo4.php

10.10.2006 - 10:03 Uhr

Folgendes Codeplex-Projekt könnte dir weiterhelfen: http://www.codeplex.com/Wiki/View.aspx?ProjectName=MassDataHandler

08.10.2006 - 08:34 Uhr

Ich denke die Koordinaten werden in Bezug zur Mitte eines "Pixels" gesetzt. Sollte dem so sein, stimmt die Darstellung schon...

07.10.2006 - 11:11 Uhr

Es gibt schon Situationen, in denen Thread Local Storage nützlich ist. Ich verwende es z.B. bei meinem Deadlock Resolver um threadspezifische Daten zu speichern. Um diese Daten von Thread zu Thread übertragen zu können musst du allerdings Hand anlegen und diese zunächst Thread Global zur Verfügung stellen um sie dann im neuen Thread wieder lokal zu speichern (wenn du dieses umkopieren benötigst, könnte dein Design aber auch ungünstig sein).

05.10.2006 - 21:07 Uhr

Original von herbivore
Hallo zusammen,

Dass das Menü nicht zuvelässig verschwindet hat mir keine Ruhe gelassen und ich habe jetzt die ultimative Lösung, die sogar ganz ohne Dummy-Control auskommt.

NotifyIcon hat eine parameterlose Methode ShowContextMenu, mit der man das eingetragene Kontextmenü anzeigen kann. Der einzige Haken ist, dass die Methode (aus mir unerfindlichen Gründen) private ist. Das ist aber in .NET dank Reflection ja keine wirkliche Klippe:

  
notico.GetType ().InvokeMember ("ShowContextMenu", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, notico, null);  
  

herbivore

Bei solchen Punkten solltest du darüber nachdenken dich bei connect.microsoft.com zu registrieren und die Vorteile einer Veröffentlichung dieser Methode als Vorschlag einbringen. Nur durch Feedback an MS kann sich in den nächsten Versionen etwas ändern...

05.10.2006 - 17:18 Uhr

Wie für alle WYSIWYG HTML-Editoren gilt auch für Visual Studio, dass der feinschliff des erzeugten HTML-Codes aufjeden Fall nochmals händisch geschehen sollte. Zumindest die Überprüfung des Codes solle man nicht überspringen. Die einzelnen ASP.Net Controls rendern aber sehr sauber und das auch in den meisten Browsern. Leider verwenden sie immernoch hautpsächlich Tabellen zur Gestaltung, aber ob das nun schlecht ist, darüber kann man sich trefflich streiten - außerdem gibt es die CSS Adapters.

05.10.2006 - 17:03 Uhr

Einen Decorator im klassischen Sinne könnte man jedoch nur implementieren, wenn die Basisklasse nicht sealed ist. Für Icon kommt dieser Ansatz also nicht in Frage. Allerdings könnte man die Remoting Proxies verwenden um das Icon dennoch zu "dekorieren". Ein möglicher Ansatz ist hier beschrieben: http://msdn.microsoft.com/msdnmag/issues/05/09/NETMatters/

Dabei stellen sich aber noch zwei Fragen:

-> Wie kann man mit Finalisieren umgehen (Thema ziemlich exklusiv: Ich gehe mal davon aus, dass ich keine Antwort bekommen werde)?
-> Die SecurityPermission Infrastructure wird benötigt. Standardmäßig wird diese nur im FullTrust Permission Set gewährt. Um meine Anwendung in einem anderen Umfeld (z.B. Local Intranet) ausführen zu können müssen also weitere Rechte manuell gewährt werden... In diesem Fall kann ich auch gleich die Reflection Permission vorraussetzen. Was bleibt somit noch der Vorteil dieses Ansatzes?

04.10.2006 - 13:46 Uhr

Das war bisher auch meine Einstellung. Über die erwähnte Alternative werde ich aber auf jeden Fall auch noch näher nachdenken...

Vielen Dank für deinen Ratschlag!

03.10.2006 - 15:46 Uhr

Solange Javascript deaktiviert ist, läuft die Seite flüssig - ansonsten ruckelt es!

/edit: FF 1.5.0.6

01.10.2006 - 19:27 Uhr

Int32 ist auch ziemlich ungeeignet zum vergleichen, da eine Wertetyp bei der Arraylist zunächst geboxt werden muss, was auch wiederum Zeit kostet. Dennoch kann ich mich dem Ratschlag die generischen Collections zu bevorzugen nur anschließen!

01.10.2006 - 17:43 Uhr

Hallo,

Bei meinem fast fertigen .Net Wrapper für die System ImageList bzw. den Shell Image Cache stellt sich noch eine abschließende Designfrage, bei der ich für jedwede Unterstützung dankbar wäre: Die WinAPI arbeit mit Icon Handles (HIcon), von diesen ausgehend muss ich ein .Net Icon erzeugen. Für diese Problemstellung gibt es eigentlich die Icon.FromHandle(IntPtr)-Methode - ein auf diese Weise erzeugtes Icon gibt das Handle beim Aufruf von Dispose (bzw. Aufruf des Finalizers) jedoch nicht frei, daher muss ich mich für eine der folgenden Alternativen entscheiden:

  1. Ich verwende Reflection um den als internal deklarierten Konstruktor Icon(IntPtr, bool) aufrufen zu können. Dieser erlaubt es ein Icon zu erzeugen, dass das Handle beim Aufruf des Finalizers oder von Dispose freigibt. Damit Aufrufer keine ReflectionPermission benötigen, würde ich die Assert-Funktion nutzen. Gleichzeitig würde ich das RequestMinimum Attribut für die entsprechende Permission nutzen, da die Library diese nun zwingend vorraussetzt.

Vorteile:

  • einfache Lösung
  • Icon-Objekte müssen nicht dupliziert werden (Icon wird bloß einmal im Speicher gehalten)
  • optimale Handle-Verwaltung
  • Änderungen am zu Grunde liegenden unmananged Icon betreffen alle auf dessen Basis erstellen .Net Icons

Nachteile:

  • Verwendung von Reflection
  • Konstruktor könnte in nachfolgenen .Net Versionen nicht mehr vorhanden sein (Versionierungsproblem)
  • Funktion undokumentiert
  • Library-Assembly benötigt entsprechende ReflectionPermission
  • Jedes Abrufen ein und des selben Icons erzeugt eine neue .Net Icon Instanz (allen liegt jedoch das selbe unmanaged Icon zu Grunde).
  1. Ich verwende Icon.FromHandle(IntPtr) in Kombination mit Icon.Clone(). Das Icon Handle wird gleich nach Aufruf der Clone-Methode wieder freigegeben und mein Wrapper liefert nur das Duplikat zurück.

Vorteile:

  • einfache Lösung
  • kein Reflection
  • Handle des Duplikats wird automatisch freigegeben (optimale Handle-Verwaltung)

Nachteile:

  • Jedes Abrufen ein und des selben Icons erzeugt eine neue .Net Icon Instanz und ein weiteres (aber identisches) unmanaged Icon
  • Das unmanaged Icon muss dupliziert werden und befindet sich daher mehrfach im Speicher
  • Änderungen am zu Grunde liegenden unamanged Icon betreffen keines der auf dessen Basis erstellten .Net Icons
  1. Ich verwende eine Kombination aus 1) und 2): Die notwendige ReflectionPermission wird als RequestOptional angegeben. Die betroffene Methode meines Wrappers überprüft zur Laufzeit, ob die ReflectionPermission gegeben ist. Sollte dies der Fall sein, wird nach Lösung 1) verfahren (inkl. Assert), ansonsten werden die Nachteile von 2) in Kauf genommen.

Vorteile:

  • Die Nachteile des zweiten Ansatzes kommen nur zum tragen, wenn der Assembly nicht die notwendige ReflectionPermission gewährt wird.
  • Setzt keine Reflection und damit verbundene Berechtigungen vorraus

Nachteile:

  • Versionierungsproblem nicht gelöst
  • weiterhin wird eine undokumentierte Funktion der Icon Klasse genutzt
  • aufwändiger
  • weiterhin wird bei mehrfachem Abruf ein und des selben Icons immer eine neue .Net Icon Instanz zurückgegeben - je nach gegebener ReflectionPermission muss zusätzlich auch das unmanaged Icon dupliziert werden
  • Ohne entsprechende ReflectionPermission steigt der Speicherbedarf
  • Ohne entsprechende ReflectionPermission steigt der Aufwand
  • Änderungen am zu Grunde liegenden unmanged Icon beinflussen die erstellten .Net Icon Instanzen nur, wenn die entsprechende ReflectionPermission gewährt wurde
  1. Ich verwende Ansatz 1) um die .Net Icons zu erzeugen. Beim ersten Abrufen eines Icons wird dieses in einem Cache mit festgelegter Cachedauer abgelegt. Wird nun ein und das selbe Icon innerhalb der Cachedauer nochmal abgerufen, wird die bereits existierende Icon-Instanz zurückgegeben. Sollte die Cachedauer bereits abgelaufen sein, muss das Icon erneut abgerufen werden und eine neue Instanz wird erstellt. Eine entsprechende Cache-Implementierung ist bereits vorhanden.

Vorteile:

  • Icon-Objekte müssen nicht dupliziert werden (Icon wird bloß einmal im Speicher gehalten)
  • Innerhalb der Cachedauer wird bei Abruf ein und des selben .net Icons immer genau eine Instanz zurückgegeben
  • optimale Handle-Verwaltung
  • Änderungen am zu Grunde liegenden unmananged Icon betreffen alle auf dessen Basis erstellen .Net Icons

Nachteile:

  • Verwendung von Reflection
  • Konstruktor könnte in nachfolgenen .Net Versionen nicht mehr vorhanden sein (Versionierungsproblem)
  • Funktion undokumentiert
  • Library-Assembly benötigt entsprechende ReflectionPermission
  • aufwändiger
  1. Ich verwende Ansatz 2) um die .Net Icons zu erzeugen. Beim ersten Abrufen eines Icons wird dieses in einem Cache mit festgelegter Cachedauer abgelegt. Wird nun ein und das selbe Icon innerhalb der Cachedauer nochmal abgerufen, wird die bereits existierende Icon-Instanz zurückgegeben. Sollte die Cachedauer bereits abgelaufen sein, muss das Icon erneut abgerufen werden und eine neue Instanz wird erstellt. Eine entsprechende Cache-Implementierung ist bereits vorhanden.

Vorteile:

  • Icon-Objekte müssen bloß selten dupliziert werden
  • Innerhalb der Cachedauer wird bei Abruf ein und des selben .net Icons immer genau eine Instanz zurückgegeben
  • Änderungen am zu Grunde liegenden unmanaged Icon werden wenigstens mit Verzögerung übernommen

Nachteile:

  • Das unmanaged Icon muss dupliziert werden (wenngleich auch bloß einmal je Cachedauer) und befindet sich daher mehrfach im Speicher
  • **Änderungen am zu Grunde liegenden unmanaged Icon betreffen keines der auf dessen Basis erstellten .Net Icons **
  • Synchronität der System Image Lists für verschiedene Icon Größen nicht mehr gewährleistet
  • aufwändiger

An dieser Stelle schon einmal vielen Dank für eure Entscheidungshilfe. Sollten euch weitere Möglichkeiten in den Sinn kommen, sind diese natürlich auch jederzeit willkommen.

Kabelsalat

01.10.2006 - 10:00 Uhr

Klar, hast recht. Habe auf die schnelle (ohne IDE vor mir) leider das falsche geschrieben. Richtig wäre folgendes: Mausklick mit rechter Maustaste -> Hinzufügen -> Vorhandenes Element... -> gewünschte Datei auswählen -> unten rechts ist ein Knopf mit Beschriftung "hinzufügen". An dessen rechter Seite ist ein Pfeil nach unten zu sehen: Wenn du diesen anklickst, erscheint ein kleines Menü, in dem du den Eintrag "Als Verknüpfung hinzufügen" auswählen solltest.