Laden...

Forenbeiträge von HiGHteK Ingesamt 114 Beiträge

16.11.2020 - 21:55 Uhr

[...]dann musst du deinen eigenen link richtig lesen[...]

Ich hab das schon richtig gelesen, du auch? 😉

Auf der von mir verlinkten Seite steht folgendes

.NET Framework 4.8 is the latest version of .NET Framework and will continue to be distributed with future releases of Windows. As long as it is installed on a supported version of Windows, .NET Framework 4.8 will continue to also be supported.

Also es wird weder eine spezifische Version noch sonst genauere Details genannt, ab wann .NET nicht mehr unterstützt wird. Und da auch verschiedene Komponenten von Windows selber auf .NET basieren, geh ich (Stand jetzt) davon aus, dass es kein zeitnahes Supportende geben wird!
Solltest du andersweitig Informationen haben, so freu ich mich auf entsprechende Quellen. Alles andere kann ich dann nur unter Gerüchte und Co verbuchen.

Darüber hinaus wurde die Aussage, wonach .NET Framework weiterhin seinen Platz haben wird, auch direkt von MS Mitarbeitern bestätigt, u.a. von Immo Landwerth (seines Zeichens Program Manager des .NET Teams bei Microsoft).
Er hat das u.a. im Gespräch mit David Tielke in folgendem Video vor knapp 2 Monaten genau so geäußert, dementsprechend kann von Abkündigung keine Rede sein!
Das Video findet sich unter DevDaily 100 - .NET und .NET Core mit Immo Landwerth, die Aussage ungefähr bei Minute 56:00

Aber insgesamt will ich darüber nun auch keine große Diskussion führen, sondern ich wollte nur deutlich machen, dass das klassisches .NET Framework nicht abgekündigt ist sondern wohl noch länger erhalten bleiben wird und man auch darauf basierende Projekte weiterführen kann.
.NET 5 und seine Nachfolger werden aber ganz klar die Zukunft sein, weil dort alles an Innovation und Co stattfinden wird. Am Ende hängt es davon ab, was man machen möchte und was einem wichtig ist.

VG.

16.11.2020 - 21:06 Uhr

.net framework ist komplett abgekündigt und es gibt nur noch den lebenslauf von .net 5

Nur um das mal klar zu stellen...Diese Aussage ist so nicht richtig.
Das klassische .NET Framework (aktuell v4.8) ist NICHT abgekündigt, sondern wird nur nicht mehr proaktiv weiterentwickelt. Aber sehr wohl noch mit Bugfixes, Sicherheitspatches und notwendigen Anpassungen (z.B. Unterstützung für TLS 1.3) versorgt und das wird wohl auch noch viele Jahre so bleiben, da es als integraler Bestandteil von Windows 10 gilt und somit auch direkt an dessen Lebenszyklus hängt. So lange also Windows 10 lebt, wird auch das klassische .NET Framework leben.
Siehe .NET Framework Support Policy (unter dem Punkt "Support lifecycle")

Das ist IMHO ein deutlichter Unterschied zu "abgekündigt" 😉

Nichtsdestotrotz seh auch ich in .NET (Core) 5 die Zukunft und wenn ich die Wahl hab, dann würde ich das wählen.

Und noch ein Hinweis zu .NET Standard...
Der wurde quasi mit dem Release von .NET 5 auch wieder "abgeschafft", d.h. es wird keinen Nachfolger von .NET Standard 2.1 geben, wenn ich das richtig verstanden habe.
Dementsprechend muss man sich damit wohl nur befassen, wenn man noch das klassische .NET Framework (was nur max. .NET Standard 2.0 unterstützt) oder .NET Core ≤ 3.1 unterstützen möchte (z.B. in Form von Nuget Paketen)
Siehe The future of .NET Standard

VG

22.07.2020 - 22:29 Uhr

Als Ergänzung...Man kann dafür auch bequem LINQ in Form der OfType<T>-Methode verwenden.

var taskAObjects = taskList.OfType<TaskA>();

Grüße

19.05.2020 - 19:49 Uhr

Hallo Abt,

danke für die zusätzlichen Infos. In den Kommentaren im Blog las sich das noch etwas anders, aber so ziehe ich meinen Einwand zurück.

Grüße

19.05.2020 - 19:40 Uhr

Ich find es schade, dass Linux nicht unterstützt wird bzw. davon keine Rede ist. Nicht das ich das nun unbedingt brauch, aber wäre irgendwie nett gewesen 😉

Aber ansonsten schließ ich mich der Aussage von T-Virus an. Etwas worauf ich schon länger warte.

Grüße

22.05.2019 - 11:41 Uhr

Hallo fichz,

ich verwende dafür gern den FluentMigrator.

Grüße, HiGHteK

31.01.2019 - 07:30 Uhr

Eine Alternative KANN an dieser Stelle dotPeek von Jetbrains sein. Neben der Möglichkeit Assemblies zu dekompilieren, kann man auch von einer Assembly PDB-Dateien generieren lassen und diese dann via lokal laufendem Symbolserver beim Debuggen via Visual Studio nutzen.
Zu beachten ist hierbei natürlich, dass man nur den kompilierten und evtl. optimierten Code debuggen kann, der sich evtl. deutlich vom Code bei Github und Co unterscheidet. Sollte aber bei Fehlersuche und Co keine entscheidende Rolle spielen IMHO.

Grüße, HiGHteK

05.10.2018 - 13:09 Uhr

Hallo HeikoAdams,

wenn du auf die UAC verzichten willst, dann solltest du deine Anwendung einfach in einen Ordner installieren in den der Benutzer schreiben darf. Im einfachsten Fall einfach unterhalb des Benutzerprofils unter C:\Users{MyUser}{MyApp}.
Läuft deine Anwendung von da, dann kannst du einfach ohne UAC Dateien kopieren und austauschen, da der Benutzer die notwendigen Zugriffsrechte schon hat (AFAIK macht es Chrome ähnlich, damit ein Update still im Hintergrund erfolgen kann).
Erscheint mir zumindest einfacher, als die UAC irgendwie umgehen zu wollen, was IMHO nicht oder nicht ohne Workarounds möglich ist.

Grüße, HiGHteK

28.11.2017 - 13:03 Uhr

Hallo Palladin007,

hast du schon mal in den Event Log (via EventViewer bzw. Ereignisanzeige) vom Betriebssystem selber nachgeschaut? Bisher hab ich da immer einen Hinweise auf die Ursache gefunden, wenn sich eine .NET Anwendung scheinbar grundlos verabschiedet hat.

Grüße, HiGHteK

05.10.2017 - 12:31 Uhr

Hallo Rabenrecht,

du musst innerhalb der Projektmappe / Solution Explorer einen Rechtsklick auf ein Projekt machen, nicht auf die Solution selber!

Grüße, HiGHteK

05.08.2017 - 23:03 Uhr

Hallo Sebastian1989101,

meine Empfehlung in diesem Fall wäre Task.CompletedTask

Grüße, HiGHteK

05.04.2017 - 21:19 Uhr

Hallo Pico1184,

ein Header besteht aus einem Schlüssel und einem Wert, du hast allerdings Schlüssel UND Wert als Schlüssel angegeben.
Versuch es mal so..

request.Headers.Add("x-netscan-auth", apiKey);

(siehe auch WebHeaderCollection.Add-Methode: (String,String))

Denn nur der Teil "x-netscan-auth: xxxxxx" beschreibt den Header im curl-Aufruf, die URL is dagegen einfach die Adresse unter der der Endpunkt erreichbar ist und somit nicht Teil des Headers.

Grüße, HiGHteK

PS: REST-Services lassen sich IMHO sehr viel komfortabler mittels RestSharp komsumieren..so als kleiner Tip 😉

02.11.2016 - 11:55 Uhr

Hallo spoochie,

eventuell hilft ein Blick in den Eventlog des Systems (gilt natürlich nur für Windows) auf dem die Exception aufgetreten ist. Vorallem nicht gefangene/behandelte Exception, die eine Anwendung zwangsweise beenden, werden dort mitunter protokolliert.

Grüße, HiGHteK

01.08.2016 - 11:13 Uhr

Ach die Treffer kann man sich auch anschauen?! 😉
Aber danke für die Hinweise, ich schau mir das alles nun mal in Ruhe an. Ist doch recht viel neues dabei..

01.08.2016 - 11:08 Uhr

Kaum zu glauben, aber die Idee hatte ich natürlich auch...
Trotzdem hat mich die Erfahrung gelehrt, dass die Anzahl der Googletreffer kein Indikator für die Qualität einer Umsetzung ist. Deswegen hatte ich die Frage nochmal hinterhergeschickt, weil hier sicher der ein oder andere schon mehr als eine REST-API mit Authentifizierung und Autorisierung umgesetzt hat und aus der Erfahrung heraus vielleicht noch etwas dazu sagen kann.
Aber ok, ich denk ich komm damit erstmal weiter und belass es dabei.

01.08.2016 - 10:46 Uhr

Hallo Abt,

danke für die Informationen, dann kann ich zumindest darauf basierend schon mal meine Suche erweitern. Ich hoffe das sich dabei auch alle noch offenen Fragen erledigen bzw. das die Umsetzung im genannten Szenario sich aus den Informationen erschließt.

Kann evtl. noch jemand etwas dazu sagen, ob NancyFX sich für ein solches Szenario (tokenbasiert, OAuth2, etc.) eignet? Muss gestehen, dass ich mich mit dem Thema Authentifizierung und Autorisierung noch nicht so intensiv auseinander gesetzt habe und hier für weiterführende Links, Informatione und Co dankbar wäre.

Danke und Grüße,

HiGHteK

31.07.2016 - 19:52 Uhr

Hallo zusammen!

Folgendes Szenario bereitet mir nun schon einige Tage Kopfzerbrechen und ich komm mit den Informationen aus Suche und Dokumentation irgendwie nicht weiter und hoffe hier eine hilfreiche Anregung zu bekommen.
Es existiert ein REST-API basierend auf NancyFX, welche eine Authentifizierung mittels Forms-Authentication anbietet. Also ein Benutzer kann sich mittels Username + Password anmelden und dann verschiedene Aktionen durchführen.
Diese Schnittstelle soll langfristig sowohl von Webanwendungen wie auch Apps genutzt werden.

Der erste (Test)client soll dabei auf ASP.NET MVC Core basieren und hier beginnt mein Verständnissproblem. Während z.B. bei einer SPA der Client direkt mit der REST-Schnittstelle kommuniziert, geschieht dies ja bei der ASP.NET Anwendung nicht, da diese Anwendung sich nach meinem Verständnis zwischen Client und Schnittstelle befindet und die Kommunikation mit der Schnittstelle übernimmt. Und genau da liegt mein Problem...Denn so landen ja auch die Authentifizierungsinformationen nicht am Client sondern im Datenzugriff der ASP.NET Anwendung und ich müsste diese von Hand immer einem Benutzer zuordnen, was ich aber gern vermeiden wollen würde, da es sich nach meinem Verständnis nicht sauber anfühlt.
Vielmehr suchte ich bisher nach einer Art Möglichkeit, wo die ASP.NET Anwendung sich mehr wie ein Proxy verhält und die notwendigen Authentifizerungsinformationen mehr oder weniger durchschleust, so dass diese beim Nutzer liegen und von der Anwendung nur für die Kommunikation verwendet werden können.

Gibt es bereits vorhandene Möglichkeiten oder ist ein solches Vorgehen eher ungewöhnlich / nicht empfohlen? Gibt es im besten Fall Alternativen, weiterführende Informationen (Dokumentation, Tutorials, etc.) oder wenigstens einen (Fach)Begriff unter dem man dazu suchen kann?

Grüße, HiGHteK

15.12.2015 - 17:08 Uhr

Wäre es an dieser Stelle nicht sehr viel einfacher fertige HTML-Seiten zu generieren auf Basis der vorhandenen Daten? Könnte mir an dieser Stelle sehr gut den Einsatz von Razor als Templateengine vorstellen.

Dann brauchst einfach nur Templates erstellen (welche sich ja auch via CSS formatieren lassen), diese mit den entsprechenden Daten füttern und anzeigen lassen. Allerdings funktioniert dies nur, wenn die Daten statisch angezeigt werden, d.h. über die Weboberfläche ist dann wahrscheinlich keine Aktualisierung der Daten möglich. Aber auch hier könntest dann drüber nachdenken, ob du einfach eine Browserengine embeddest und die Anzeige der generierten HTML-Seiten darüber realisierst.
Dann kommst quasi ganz ohne Webserver aus und kannst bei Bedarf die Anzeige aktualisieren...

Ansonsten klingt das für mich grundsätzlich nach Reporting, auch da gibt es bereits fertige Bibliotheken mit denen man entsprechene Reports in HTML, PDF und Co erzeugen kann. Evtl. lassen sich mit den Suchbegriffen auch noch nützliche Antworten finden.

Aber das nur mal als Anregung und Möglichkeit, dass ganze ohne einen Webserver zu realisieren. Klingt für mich irgendwie nach Kanonen und Spatzen 😉

Grüße, HiGHteK

06.08.2015 - 16:41 Uhr

Hallo Ismoh,

na wenn dann eher mittels Type.GetFields.

Wie bereits gesagt wurde, hat die Bezeichnung "Attribut" im Umfeld von .NET eine andere Bedeutung.

Ich möchte die Felder der Objekte in eine Datei speichern

Wenn es wirklich nur darum geht, dann kanst du dich auch mal mit dem Thema Serialisierung beschäftigen.Damit kannst du den Zustand eines Objekts binär, als XML, JSON, ... speichern.

Grüße, HiGHteK

06.07.2015 - 16:51 Uhr

'string' enthält keine Definition für 'SubString'

Die Methode heißt ja auch Substring ..

Grüße, HiGHteK

02.06.2015 - 12:58 Uhr

MyNode soll irgendeine Eigenschaft besitzten anhand derer ich ein bestimmtes Form identifizieren kann, so dass das Form beim MausKlick auf den TreeView Node instanziiert /aufgerufen, irgendwas mit gemacht wird.

Ich würde an dieser Stelle einfach auf DependencyInjection bzw. das MEF zurückgreifen. Alle Elemente, die angezeigt werden müssen, werden mittels gemeinsamer generischer Schnittstelle abgebildet, im einfachsten Fall sowas wie

public interface INode
{
	void Show();
}

Die Implementierungen können nun relativ einfach von deiner Basisklasse ableiten

[NodeMetadata("NodeA")]
public class NodeAForm : MyGenericForm<AObject>, INode
{
	public void Show()
	{
		//...
	}
}

und via Attributen bzw. Metadaten kann deklariert werden, für welchen Node sie zuständig sind.

Nun kann man sich via MEF alle Implementierungen einer Schnittstelle (z.B. INode) holen, die Metadaten auswerten und so die zu einem Node passende Implementierung ermitteln.
Nun einfach Show() an dieser Implementierung bzw. Instanz aufrufen und voila...Ohne Reflection, switch case oder sonstigem bekommt man die zu einem Node passende Form angezeigt. Und erweiterbar ist das ganze auch sehr einfach, da man für jeden neuen eindeutigen Wert einfach eine neue Implementierung der Schnittstelle erstellt.

Mir ist durchaus bewusst, dass meine Erklärung sehr komprimiert ist und evtl. nicht alle angesprochenen Technologien und Vorgehen bekannt sind, aber mit etwas Eigeninitiative sollte sich zu allem was finden lassen und bei konkreten Fragen einfach wieder hier im Forum nachfragen 😉

Grüße, HiGHteK

08.12.2014 - 09:54 Uhr

Danke nochmals für deine Hilfe.
Auch der zuletzt von dir angesprochene Aspekt ist mir bekannt, hätte das Problem aber nur unzureichend gelöst. Ich gebe auch gern zu, dass ich VB.NET bisher bewusst gemieden habe 😉

Aber wie bereits angesprochen konnte ich mein Problem sehr viel einfacher lösen, als nun extra eine Klasse in einem C#-Projekt anzulegen, um diese mittels dem existierenden VB-Projekt zu erweitern / zu nutzen. Ich hab tatsächlich nur einen kleinen Denkanstoss gebraucht.

Grüße, HiGHteK

05.12.2014 - 20:28 Uhr

Du weist schon das man in VB.NET auch locker jede C# DLL benutzen kann?

Ja dieser Umstand ist mir bekannt. Allerdings kann man VB und C# nicht innerhalb eines Projektes mischen und das Projekt mit der problematischen Servicereferenz ist halt ein VB.NET-Projekt. Und nur die Servicereferenz in ein C#-Projekt auslagern ging auch nicht, da da noch bisschen mehr (VB.NET)-Code dran hing.

Aber ganz abgesehen davon könntest du auch einfach jeden Webservice in eine eigene DLL packen,
dann kannst du den Namespace auch verändern.

Danke, genau das hab ich dann auch getan. Keine Ahnung warum ich nicht gleich daran gedacht hatte diesen monolitisch anmutenden Service aufzuteilen 🤔

Grüße, HiGHteK

05.12.2014 - 10:29 Uhr

Hallo zusammen,

ich hoffe ich bin hier mit meinem Anliegen richtig, auch wenn es nur bedingt mit der WCF zu tun hat, aber alle anderen Kategorien erschienen mir noch unpassender.

Folgendes Problem...
Aktuell muss ich eine ältere Anwendung pflegen, die komplett in VB.NET (hab selber bisher immer in C# entwickelt) entwickelt wurde. Diese nutzt verschiedene Webservices (Java+Tomcat+JAX-WS) via Servicereference, so dass alle notwendigen Klassen anhand der WSDL automatisch generiert werden.
Nach Aktualisierung der Servicereferenz tritt nun leider ein Fehler auf, weil 2 Klassen Query und query generiert wurden. Wie ich daraufhin lernen musste unterscheidet VB.NET hier nicht zwischen Groß- und Kleinschreibung und beschwert sich somit zu recht, dass es 2 Klassen mit dem selben Namen gibt bzw. das an einer Klasse Query ein Attribut mehrfach definiert wurde.
Gibt es irgendeinen Ausweg aus diesem Problem? Kann man dem Generierungsprozess irgendwie sagen, dass er die Typen bitte in verschiedene Namespaces packen soll, da diese auch innerhalb der WSDL in verschiedenen XML-Namespaces liegen?

Einzige Möglichkeiten, die mir bisher eingefallen sind, wäre entweder die Anpassung der Serverseite oder Umstellung des Projekts auf C# auf Clientseite...beides mit erheblichem Aufwand verbunden und somit nicht in meinem engeren Favoritenkreis 😉

Für jegliche Anregungen bin ich dankbar ..

Grüße, HiGHteK

02.09.2014 - 12:50 Uhr

Es ist zwar schon eine Weile her das ich mit DataTables gearbeitet habe, aber kannst du nicht einfach für die Spalte den DefaultValue setzen? Laut MSDN wird dann für jede neue Reihe automatisch der festgelegte Wert verwendet und müsste somit nicht mehr manuell definiert werden.

Grüße, HiGHteK

10.04.2014 - 09:15 Uhr

Hallo Geaz,

hab mir eben mal deine Testseite unter http://test.boxxnet.de/ angeschaut und bekomme diese leider nicht richtig angezeigt (siehe Navigationsbereich im Screenshot). Browser ist Opera in der Version 20.0.1387.91.
Aber ansonsten macht es einen guten Eindruck, werd ich die Tage mal ausprobieren und gegen ein kleines Projekt von mir laufen lassen.

Grüße, HiGHteK

02.04.2014 - 08:26 Uhr

Hallo Potestas,

da ich aktuell auch ein Projekt mit Prism umsetzen darf, hat mich die Frage interessiert und ich habe mal einen Blick in den Sourcecode von Prism geworfen.
Das Verhalten was du beobachtest, hat nichts direkt mit der Oberfläche zu tun. Aber bei dem DelegateCommand gibt es etwas wichtiges zu beachten...
Abonenten des CanExecuteChanged-Events werden vom DelegatCommand nur als schwache Referenz gehalten. Das heißt wenn sonst keine Referenz mehr auf dieses Objekt existiert, kann es passieren, dass der GC das Objekt abräumt, bevor der Event ausgelöst wird! Bindest du das Command an einen Button, so wird dieser als "harte" Referenz innerhalb der Oberfläche gehalten und es funktioniert wie erwartet.
Das Ganze steht auch so in der Dokumentation, siehe DelegateCommandBase.CanExecuteChanged Event (Remarks-Abschnitt)

Grüße, HiGHteK

31.03.2014 - 09:12 Uhr

Hallo,

ich hatte bisher noch keine Anstellung, bei der ich ausschließlich zu Hause gearbeitet habe. Allerdings schon die Möglichkeit einzelne Tage oder Stunden nach eigener Einteilung in meine eigenen 4 Wände zu verlegen.
Und ich muss sagen gerade dieser hybride Ansatz aus normalem Firmenarbeitsplatz mit Möglichkeit für Homeoffice hatte für mich einige Vorteile. Angefangen von mehr Freiheiten beim Vereinbaren privater Termine (Arzt, Handwerker, Lieferungen, etc.) bis hin zu effizientem Arbeiten in einer ruhigen Umgebung, wenn man mal ein anspruchsvolleres Problem zu lösen hatte.
Allerdings ist natürlich nicht alle Gold was glänzt...Die Kehrseite der Medaille gibt es natürlich auch. Man muss recht klar und deutlich eine Trennung zwischen Arbeit und Privatleben schaffen, da sonst schnell Probleme auftreten weil manch einer der Meinung sein könnte, man wäre dann immer erreichbar und in der Lage schnell was zu erledigen. Dem muss man evtl. ganz bewusst entgegen steuern, sonst sitzt man auch am Wochenende an irgendwelchen "total wichtigen" Sachen und baut unnötig viele Überstunden auf 😉

Grüße, HiGHteK

26.03.2014 - 07:49 Uhr

Hallo herbivore,

Die Elemente, die in l2, aber nicht in l1 enthalten sind, kann man auf die gleiche Weise ermitteln. Man muss nur die beiden Listen-Variablen vertauschen.

Danke für die ergänzende Anmerkung. Ich gebe zu das meine zusätzliche Bemerkung etwas unglücklich formuliert ist, aber genau darauf abzielen sollte. Ich ging auch einfach davon aus, dass das jedem klar sein sollte, spätestens beim Blick in die verlinkte Dokumentation 😉

Grüße, HiGHteK

25.03.2014 - 15:00 Uhr

Hallo Damlo,

ich glaube der Beitrag bewegt sich hart an der Grenze zu einem Grundlagenbeitrag.
Aber als kleiner Hinweis...
Wenn die Spaltennamen in jeweils 2 Listen mit Strings vorliegen und du nur die Unterschiede wissen möchtest, so kannst du der Einfachkeit halber auch auf Enumerable.Except zurückgreifen.
Als Ergebnis bekommt dann eine Auflistung der Unterschiede, welche du problemlos weiterverwenden kannst (z.B. für die Anzeige an der Oberfläche).

Beispielcode:

List<string> l1 = new List<string>(new string[] { "Foo", "Bar", "Baz" });
List<string> l2 = new List<string>(new string[] { "Foo", "Bar" });
List<string> diff = l1.Except(l2).ToList(); //diff enthält nun nur noch "Baz"

Edit: Ich muss meinen Lösungsvorschlag einschränken...Bei Enumerable.Except werden nur die Elemente zurückgegeben, die in l1, aber nicht in l2 enthalten sind. Elemente die in l2, aber nicht in l1 enthalten sind, werden nicht zurückgegeben!

Grüße, HiGHteK

07.02.2014 - 10:33 Uhr

Hallo charger472,

hast du dir in dem Zusammenhang schon mal das FlowLayoutPanel angeschaut? Das layoutet sich automatisch, so wie neuer / weiterer Inhalt eingefügt wird.

Grüße, HiGHteK

20.01.2014 - 14:38 Uhr

Hallo Muck92,

die ObservableCollection selber bietet keine Möglichkeit dafür, sondern löst nur ein Event aus, wenn sich die Collection an sich ändert.
Um die Elemente innerhalb der Auflistung zu überwachen, müssten diese selber einen Event bereitstellen (z.B. via INotifyPropertyChanged) und du müsstest dieses Event für jedes einzelne Objekt registrieren (und später natürlich auch wieder deregistrieren!).
Alternativ kannst du natürlich auch eine spezialisierte Collection dafür selber implementieren und dabei z.B. auf Weak Event-Mechanismen zurückgreifen.

Grüße, HiGHteK

17.01.2014 - 10:24 Uhr

Hallo JMano,

Ich habe mal den Ersteller (alter Kollege) angeschrieben, ober nicht doch den Quell Code irgendwo hat, um drinnen zu schauen was da passiert.

als kleiner Hinweis. Du kannst auch selber in einer DLL nachschauen, was da konkret passiert. Dazu gibt es sogenannte Decompiler (z.B. ILSpy, dotPeek, etc.).
Nutze ich auch gern mal, wenn ich einfach wissen möchte, was konkret in einer Methode passiert und ich den Sourcecode eben nicht vorliegen hab. Bietet sich auch bei Klassen des .NET-Frameworks immer mal wieder an (auch wenn mir bewusst ist, dass man diese sogar via Visual Studio debuggen kann, aber meist reicht mir ein Blick).

Grüße, HiGHteK

12.12.2013 - 15:06 Uhr

Hallo MysticEmpires,

ich würde an dieser Stelle auf die Definition von Knoten im XAML verzichten, auch wenn ein Teil statisch ist. Wenn du es komplett in MVVM umsetzt, dann definierst du einfach ein ViewModel für einen Knoten im Baum und organisierst diese in einer Hierarchie. Das heißt jedes NodeViewModel hat wiederum eine Auflistung von NodeViewModels.
Alle statischen Knoten legst nun einfach einmalig im Code beim Erzeugen des ViewModels für den TreeView an und alle dynamischen eben zu dem Zeitpunkt, wo du die Daten zu diesen liest. Und jeder dynamische Knoten bzw. deren ViewModel erstellt dann einfach bei der Erzeugung wiederum die fix benötigten Knoten.
Dann hast du alle notwendigen Knoten, egal of fix oder dynamisch, in einer Datenstruktur und kannst das nach belieben Erweitern, Umsortieren, Knoten entfernen oder was auch immer eine zukünftige Anforderung sein könnte 😉

Grüße, HiGHteK

06.12.2013 - 15:24 Uhr

Hallo brainwave,

ich wage mal zu behaupten, dass der Code aus deinem ersten Post keinen Sinn ergibt 🤔
Wieso übergibst du in der Methode CastTo einen Parameter t vom Typ T, wenn du diesen innerhalb der Methode gar nicht verwendest?
Oder soll deine Variable myFooObject nach Aufruf der Methode CastTo das gecastete Objekt enthalten? Wobei selbst das keinen erkennbaren Sinn macht, weil du dann auch schreiben kannst..

Foo myFooObject = (myFooObject)varObject;

Deshalb schließe ich mich MrSparkle an..

Was meinst du damit konkret? bzw. was möchtest du erreichen?

Grüße, HiGHteK

28.11.2013 - 10:59 Uhr

Hallo steven,

ganz grundsätzlich hast du schon richtig erkannt, dass irgendeine Resource deine Dateien noch im Zugriff hat.
Und im konkreten Fall würde ich auf die Instanz(en) vom Typ PdfReader tippen, da du diese, zumindest in dem von dir geposteten Code, nicht schließt. Und da du beim Erstellen einer Instanz immer eine deiner PDF-Dateien als Parameter angibst, wird der Zugriff auf diese wohl nicht freigegeben.
Sofern der PdfReader IDisposable implementiert, solltest du diesen ebenfalls in einem using-Block verwenden.

Grüße, HiGHteK

14.11.2013 - 13:40 Uhr

Hallo Mossi,

wenn ich das richtig verstehe, willst du mit dem erstellten Delegaten vom Typ Func<IDomainObject, bool> eine Liste List<IDomainObject> filtern, in der nur Objekte genau eines Types enthalten sind, den du als String bekommst? Soweit richtig?

Wenn ja, dann könnte Expression.Convert eine Lösung für dich sein. Damit kannst du deinen Parameter vom Typ IDomainObject beim Zugriff jedesmal in den konkreten Typen casten.
Aber Achtung...Diese Lösung erfordert es, dass die Typen dann zur Laufzeit eben auch passen! Eine Liste von IDomainObject-Objekten kann ja theoretisch auch aus DomainObject1 und DomainObject2-Objekten bestehen und dann geht es zur Laufzeit kaputt 😉

Kurz und knapp...den Code aus dem ersten Post


private static Expression GetFilterExpression(Type realtype, ParameterExpression param, ILookup filter)
{
    MemberExpression member = Expression.Property(param, realtype.GetPropertyExt(filter.Column));
    ConstantExpression constant = Expression.Constant(filter.Value);
	...

könntest du ersetzen mit...


private static Expression GetFilterExpression(Type realtype, ParameterExpression param, ILookup filter)
{
    MemberExpression member = Expression.Property(
		Expression.Convert(param, realtype), 
		realtype.GetPropertyExt(filter.Column));
    ConstantExpression constant = Expression.Constant(filter.Value);
	...

param repräsentiert eine ParameterExpression vom Typ IDomainObject, während realtyp den echten .NET-Laufzeittyp (z.B. DomainObject1) repräsentiert.
Hoffe ist soweit verständlich, Code habe ich nicht getestet sondern hier im Editor runter getippt...Also kein Gewähr auf Fehlerfreiheit 😉

Grüße, HiGHteK

12.11.2013 - 12:00 Uhr

Hallo Daniel_3_17,

ich kann an dieser Stelle auch noch Nancy empfehlen. Klein, leichtgewichtig und wunderbar einfach in Betrieb zu nehmen...Hatte ich vor knapp einem halben Jahr bei einem Projekt verwendet, wo ich vor genau der selben Frage stand.

Edit: Vielleicht noch kurz als Begründung, warum Nancy...WCF war mir deutlich zu aufwändig und die Lernkurve bei meinen Anforderungen deutlich zu steil...
Und ASP.NET Web Api war zum damaligen Zeitpunkt deutlich weniger charmant zu konfigurieren, vorallem was das Routing anging. Wobei sich AFAIR da etwas getan hat mit dem letzten Release.

Grüße, HiGHteK

24.10.2013 - 08:41 Uhr

Hallo vreden123,

wenn es lizenzrechtlich aus Sicht von Truecrpyt keine Probleme gibt, dann könntest du auch die Portable-Version von Truecrypt deiner Anwendung beifügen, um die Installation zu vermeiden. Nur so als Idee..

Grüße, HiGHteK

22.10.2013 - 11:09 Uhr

Hallo nina-nanu,

noch eine Kleinigkeit...Ich hab mir eben das von dir angehängte Beispiel angeschaut und dabei folgendes festgestellt...
Du nutzt zur Darstellung des DataGrids folgenden XAML-Code:

<StackPanel>
    <Button Name="btnCreateDataTable" Content="Create DataTable with sample content" Click="btnCreateDataTable_Click" />
    <Button Name="btnSetDataContext" Content="Bind DataTable to DataGrid" Click="btnSetDataContext_Click" />

    <DataGrid Name="grdExcel" ItemsSource="{Binding DataTableWithExcelContent}" AutoGenerateColumns="True" />
        
</StackPanel>

Änderst du diesen allerdings wie folgt ab, bleibt die Darstellung gleich, aber die Performance wird deutlich besser:

<DockPanel>

    <StackPanel DockPanel.Dock="Top">
        <Button Name="btnCreateDataTable" Content="Create DataTable with sample content" Click="btnCreateDataTable_Click" />
        <Button Name="btnSetDataContext" Content="Bind DataTable to DataGrid" Click="btnSetDataContext_Click" />
    </StackPanel>

    <DataGrid Name="grdExcel" ItemsSource="{Binding DataTableWithExcelContent}" AutoGenerateColumns="True" />

</DockPanel>

ich bin nun kein XAML-Experte, aber ich vermute folgendes...
Ist das DataGrid in dem StackPanel, so werden sofort alle Elemente für die Darstellung berechnet, da das StackPanel keine maximal mögliche Höhe vorgibt und somit die Virtualisierung der darzustellenden Elemente nicht greifen kann. Dies sieht man auch daran, dass zum DataGrid keine Scrollbars angezeigt werden...
Steckt man das DataGrid aber nun in den DockPanel, so bekommt dieses nur eine bestimmte Höhe als maximal möglichen Wert. Dadurch kann nun die Virtualisierung greifen, da nur noch eine bestimmte Menge an Elementen sichtbar ist und dargestellt werden muss.
(Dies kann man by the way auch noch erreichen, in dem man dem DataGrid eine maximale Höhe innerhalb des StackPanel zuweist.)
Diese Angaben sind ohne Gewähr, da sie nur auf meinen Beobachtungen basieren, evtl. kann das jemand aus dem Forum fundierter begründen und bestätigen oder korrigieren. 😉
Aber vielleicht hilft dir diese Beobachtung ja schon weiter...

Grüße, HiGHteK

15.10.2013 - 08:59 Uhr

Hallo scrabbl,

Nur so langsam ist es mir etwas zu alt. Da damit weder x64 vernünftig geht noch ein .NET Framework über 3.5 suche ich jetzt nach Alternativen da das nicht mehr supported wird scheinbar.

Ich glaube deine Informationen sind nicht ganz aktuell 😉 Unter http://www.firebirdsql.org/ findest du sowohl die aktuelle Version der Firebird-Datenbank (in 32- und 64-bit sowie als Server- und Embeddedvariante) sowie eine aktuelle Version des dazu passenden ADO.NET-Providers.

Grüße, HiGHteK

10.10.2013 - 11:06 Uhr

Hallo BlackMatrix,

dann würde ich an deiner Stelle einfach einen Appender / Service implementieren, der die Logeinträge im Speicher vorhält und zur Verfügung steht (inkl. Benachrichtigung bei neuen Einträgen). So kann sowohl deine Oberfläche bzw. das ViewModels diese abrufen und bereit stellen und du kannst sie auch jederzeit weiterverwenden, wenn sie nochmals irgendwo gebraucht werden. Kurz, ich würde diese Anforderung von der Anzeige an der Oberfläche entkoppeln.
Aufpassen solltest du aber dabei, dass bei sehr vielen Logeinträgen ältere eventuell auch mal wieder entfernt werden, da dir sonst irgendwann der Speicher voll läuft 😉

Grüße, HiGHteK

02.10.2013 - 08:14 Uhr

Hallo dr4g0n76,

da hat sich ein Fehler eingeschlichen...Mittels

public static Delegate CreateDelegate(MethodInfo method, object @object)
{
	return Delegate.CreateDelegate
	(
		Expression.GetDelegateType
		(
			method.GetParameters()
				.Select(p => p.ParameterType)
				.Concat(new Type[] { method.ReturnType })
				.ToArray()
		),
		@object,
		method
	);
}

erstellst du einen Delegaten genau für den Zugriff auf die Eigenschaft des Objekts o. Sprich beim Aufruf des Delegaten solltest du immer die gleiche Id erhalten, da ja an die Methode niemals das jeweils aktuelle Objekt (aus der foreach-Schleife) übergeben wird.

Und noch als kleine Anmerkung...Auf die Verwendung von DynamicInvoke() sollte man verzichten, da diese sehr inperformant ist und eigentlich nur gebraucht wird, wenn der Typ des Delegaten gänzlich unbekannt ist. Aber da du ja sowohl Typ wie auch Eigenschaft mehr oder minder kennst, kannst du einen typisierten Delegaten (z.B. Func<T, string>) via ExpressionTree erstellen oder eben Reflection verwenden...beides sollte deutlich schneller als DynamicInvoke() sein!

Grüße, HiGHteK

30.09.2013 - 16:26 Uhr

Die Thematik kommt mir grob bekannt vor, deswegen wäre vielleicht ein anderer Lösungsansatz die Verwendung von ExpressionTrees...
Allerdings sollte hier die Thematik Performance eingehend betrachetet werden, da dass Kompilieren von ExpressionTrees zur Laufzeit richtig Zeit kosten kann, wenn man das sehr oft und immer wieder macht 😉
Ansonsten zeigt ein kleines Beispiel hoffentlich ausreichend, was ich mein...Dann kann ich mir große Worte sparen 😉 Allerdings ist dies nur ein Konstrukt um die grundlegende Idee zu veranschaulichen, nicht um dies produktiv zu übernehmen...Nur nochmal als Klarstellung!

class Program
{
    static void Main(string[] args)
    {
        var foos = Foo.Create(10);
        var bars = Bar.Create(10);

        var foo5 = GetById<Foo>(foos, "5");
        var bar7 = GetById<Bar>(bars, "623fdeff-95ab-4386-bfd6-754d032bea17");
    }

    private static MethodInfo __toStringMethodInfo = typeof(object).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public);
    private static T GetById<T>(IEnumerable<T> items, string id)
    {
        var param = Expression.Parameter(typeof(T), "x");
        var expression = Expression.Lambda<Func<T, bool>>(
            Expression.Equal(
                //Der Call ruft ToString() an der Eigenschaft Id auf
                Expression.Call(
                    Expression.Property(param, "Id"),
                    __toStringMethodInfo),
                Expression.Constant(id)),
                param);

        //Alternativ kann hier die Expression auf via Compile() in eine Func<T, bool> umgewandelt werden
        //und man kann auf AsQueryable() verzichten...
        //An dieser Stelle müsste man untersuchen, was sich aus Sicht von Performance und Co eher anbietet
        //und man sollte ein Caching einbauen, um die Erstellung der Expression bzw. Func nur einmalig je
        //Typ machen zu müssen!
        var result = items.AsQueryable().Where(expression).FirstOrDefault();
        return result;
    }

    public class Foo
    {
        public int Id { get; set; }

        public static IEnumerable<Foo> Create(int count)
        {
            var result = new Foo[count];

            for (int i = 0; i < count; i++)
            {
                result[i] = new Foo()
                {
                    Id = i + 1
                };
            }

            return result;
        }
    }

    public class Bar
    {
        public Guid Id { get; set; }

        public static IEnumerable<Bar> Create(int count)
        {
            var result = new Bar[count];

            for (int i = 0; i < count; i++)
            {
                result[i] = new Bar()
                {
                    Id = Guid.Parse("623fdeff-95ab-4386-bfd6-754d032bea1" + i.ToString())
                };
            }

            return result;
        }
    }
}

Wirklich unschön ist dabei sicherlich, dass die Eigenschaft Id als Zeichenkette hinterlegt ist und verwendet wird....Bei einem Refactoring wird sowas sicherlich schnell mal vergessen...
Ansonsten ist es wie gesagt auch nur eine Idee, die mir bei der Problematik so durch den Kopf schoss 😉

Grüße, HiGHteK

PS: Ganz wird hierbei natürlich nicht auf Reflection verzichtet, da diese schon bei der Erstellung des ExpressionTrees zur Validierung herangezogen wird...Allerdings wird diese dann auch nur einmalig benötigt, wenn man das Ergebnis (wie im Kommentar angeregt) cacht..

13.09.2013 - 09:17 Uhr

Hallo herbivore,

ich hatte befürchtet, dass ich irgendwas übersehen hab. Aber ich hab die obige Implementierung noch um eine Zeile ergänzt, um den Fehler aus deinem Beispielfall zu eliminieren...
Allerdings kann ich mangels Zeit nicht weiter darüber sinnieren, aber ich hoffe die Implementierung ist nun im Großen und Ganzen soweit OK 😉

Hier nochmals die korrigierte Implementierung...

public static bool Contains<T>(this IEnumerable<T> source,
    IEnumerable<T> needle,
    IEqualityComparer<T> comparer)
{
    if (!needle.Any())
        return false;

    var firstNeedle = needle.First();
    var needleEnumerator = needle.Skip(1).GetEnumerator();

    bool itemsAreEqual = false;

    foreach (var item in source)
    {
        if (!itemsAreEqual)
            itemsAreEqual = comparer.Equals(item, firstNeedle);
        else
        {
            if (!needleEnumerator.MoveNext())
                return true;
            else
            {
                itemsAreEqual = comparer.Equals(needleEnumerator.Current, item);
                if (!itemsAreEqual)
                {
                    itemsAreEqual = comparer.Equals(item, firstNeedle);
                    needleEnumerator = needle.Skip(1).GetEnumerator();
                }
            }
        }
    }

    return itemsAreEqual;
}

Grüße, HiGHteK

12.09.2013 - 15:44 Uhr

Hallo zusammen,

ich hab mich auch mal eben daran versucht, weil es als kurze Ablenkung genau richtig kam 😉

public static bool Contains<T>(this IEnumerable<T> source,
    IEnumerable<T> needle,
    IEqualityComparer<T> comparer)
{
    if (!needle.Any())
        return false;

    var firstNeedle = needle.First();
    var needleEnumerator = needle.Skip(1).GetEnumerator();

    bool itemsAreEqual = false;

    foreach (var item in source)
    {
        if (!itemsAreEqual)
            itemsAreEqual = comparer.Equals(item, firstNeedle);
        else
        {
            if (!needleEnumerator.MoveNext())
                return true;
            else
            {
                itemsAreEqual = comparer.Equals(needleEnumerator.Current, item);
                if (!itemsAreEqual)
                    needleEnumerator = needle.Skip(1).GetEnumerator();
            }
        }
    }

    return itemsAreEqual;
}

In einem schnellen Test hat es geklappt, keine Ahnung wie robust oder performant das insgesamt ist 😉

Grüße, HiGHteK

25.07.2013 - 10:41 Uhr

Gratulation zu 10 Jahren und ich hoffe auf noch viele weitere 😉
Und natürlich auch ein persönlicher Dank an alle Beteiligten und die Hilfestellung über die Jahre.

Grüße, HiGHteK

19.06.2013 - 10:46 Uhr

Hallo chillic,

also wenn der Benutzer eh angeben muss, welchen Delegaten er erwartet, dann wäre eventuell folgender Ansatz für dich interessant...
Eine Klasse dient als "Cache" für alle registrierten Methoden, wobei diese beim Registrieren und Abrufen via Generics auf den richtigen Typ eingeschränkt sind

public class DelegateCache
{
    private Dictionary<string, object> _cache = new Dictionary<string, object>();

    public void Register<TDelegate>(string name, TDelegate del)
    {
        _cache[name] = del;
    }

    public TDelegate Get<TDelegate>(string name)
    {
        return (TDelegate)_cache[name];
    }
}

(im Dictionary muss object (anstatt bspw. Delegate) verwendet werden, da Delegates, wie du deine Fragestellung auch zeigt, keine gemeinsame Basis haben. Da das aber nur intern verwendet wird, ist das m.M.n kein Problem)

Und verwenden könnte man das Ganze wie folgt

class Program
{
    static void Main(string[] args)
    {
        DelegateCache cache = new DelegateCache();
        cache.Register<Func<int, int, string>>("Add", MyMethod);

        Func<int, int, string> func = cache.Get<Func<int, int, string>>("Add");
        string result = func(1, 2);
    }

    private static string MyMethod(int a, int b)
    {
        return (a + b).ToString();
    }
}

Ich hab dabei auf das Definieren eigener Delegaten verzichtet, da ich bisher mit Func<...> und Action<...> immer ans Ziel gekommen bin 😉
Achtung! Das ist nur eine Idee, die ich auf die schnell runtergetippt hab...Es ist natürlich keinerlei Validierung oder Optimierung drin 😉

Grüße, HiGHteK

06.06.2013 - 08:47 Uhr

Hallo ChrisProg,

nur als mehr oder minder allgemeiner Hinweis. Wenn du eine Anwendung mit dem Debugger untersuchst, so dauern viele Arbeitsschritte nur wegen dem angehängte Debugger schon deutlich länger. Für belastbare Performanceuntersuchungen sollte man nach Möglichkeit optimierten Code ohne Debugger laufen lassen und ggf. geeignete Messinstrumente (z.B. Programme zur Performancemessung) heranziehen.

Grüße, HiGHteK

17.04.2013 - 21:46 Uhr

Hallo GeneralKampfKeks,

wenn du schreibst, dass du mit Events arbeitest, verwendest du dabei evtl. Implementierungen von IWeakEventListener und gibst in der Methode ReceiveWeakEvent(Type, object, EventArgs) false zurück?
Wenn ja, dann kann das die Fehlerursache sein. Denn in die gleiche Problematik bin ich schon mal gestolpert und hatte eine sehr ähnliche Fehlermeldung. Bis ich aber darauf gekommen bin, dass es an der Rückgabe von false lag, verging einiges an Zeit ...
Ursache bei mir war jedenfalls, dass bei Rückgabe von false in den Tiefen des .NET Framework Environment.FailFast() aufgerufen wird, was eine solche Exception auslöst.

Vielleicht hilft dir das ja weiter 😉

Grüße, HiGHteK