Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von Uwe81
Thema: Mehrere Enumerables ohne großen Buffer zusammenfassen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

Ich habe ein Array von Enumerables


IEnumerable<T>[] sources;

Typischerweise iterieren diese Enumerables nicht schnell, sind z.B. Dateien aus einem Document Management System. Der Overhead ist hoch, sodass sich wegen der hohen Latenz Parallelisierung lohnen würde, z.B. weil ich bei drei verschiedenen Repositories Dokumente runterlade.

Das Interface gibt mir für ein Repository alle Dokumente als IEnumerable<T>


Jetzt suche ich ein Enumerable, was sich wiefolgt berechnet.
Für jedes Sourceelement gibt es einen kleinen Buffer.
Die Enumerables werden parallel durchlaufen, d.h. wenn der Buffer für ein Enumerable nicht mehr gefüllt ist, wird das nächste Element bereits abgerufen.
Wenn ich für das "merged Enumerable" das nächste Element abfrage, erhalte ich irgend eines aus den buffern der unterliegenen enumerables, oder halt das nächste was da ist.


Ich bin neun in Tasks, PLINQ und parallel foreach. Daher verliere ich mich bei der Implementierung.

Das beste was ich bisher hinbekommen habe ist eine manuelle Implementierung mit Blocking Collections (noch nicht getestet)
Geht das wirklich nicht eleganter?


        public int MaxCapacity { get; set; }
        public IList<IIterateStrategy> IterateStrategies { get; set; };

        public IEnumerable<DSDownloadEntry> Iterate() {
            var collection = new BlockingCollection<DSDownloadEntry>(MaxCapacity);
            var tasks = new Task[IterateStrategies.Count];
            for(int i = 0; i<IterateStrategies.Count; i++) {
                int index = i;
                var strategy = IterateStrategies[index];
                tasks[i] = Task.Factory.StartNew(() => {
                    foreach (var item in IterateStrategies[index].Iterate()) {
                        collection.Add(new DSDownloadEntry() { Container = item });
                    }
                });
            }
            Task.Factory.ContinueWhenAll(tasks, _ => collection.CompleteAdding());
            return collection.GetConsumingEnumerable();
        }



Ergänzung:

Ich habe jetzt nochmal PLINQ versucht:


    class Producer {
        public string Prefix;
        public int Count;

        public IEnumerable<string> GetResults() {
            Random random = new Random();
            for (int i = 0; i < Count; i++) {
                var text = string.Format("{0}{1:000000}", Prefix, i);
                Console.WriteLine("Producing " + text);
                yield return text;
            }
            Console.WriteLine("############### DONE " + Prefix);
        }
    }
    class Program {
        public static void Main() {
            var producers = new[] {
                new Producer() {Prefix = "A", Count = 100000},
                new Producer() {Prefix = "B", Count = 100000},
                new Producer() {Prefix = "C", Count = 100000},
            };

            var merged = from p in producers.AsParallel()
                         from r in p.GetResults()
                         select r;

            foreach (var r in merged) {
                Console.WriteLine("Consumint " + r);
            }
        }
    }

Das Problem hier ist, das der Producer bereits weiterläuft, auch wenn nur wenig abgerufen wird.
Eine ergänzung "AsParallel().WithMergeOptions" hat nichts verändert.

Mein Wunsch wäre eben, dass pro Producer nur wenige Einträge gebuffert werden.

Thema: Command in CodeBehind ohne Assembly-Referenz
Am im Forum: GUI: WPF und XAML

Wenn ich die Anwendung selbst in der Hand hätte, würde ich die Assembly-Aufteilung auch nicht so machen.

So ist es aber, dass die Anwendung meinen Code per COM-Schnittstelle aufruft, ich dann meinerseits eine Methode aufrufe, die mein Control erzeugt und in einem vorgegebenen Rahmen anzeigt. Dabei müssen die Assemblies aber an unterschiedlichen Stellen liegen, insbesondere das Control in einem bestimmten Unterordner des Programms.

Jetzt habe ich es erstmal so gelöst, dass ich mir per Reflection das Command als ICommand hole.

Sollten noch weitere Abhängigkeiten entstehen, muss ich das nochmals überdenken. Allerdings weiß ich garnicht so genau, wo dann das gemeinsam bekannte Interface-Assembly liegen soll. Im Ordner der View? Im Ordner der Logik (die per COM-Interface angestoßen wird).

Thema: Command in CodeBehind ohne Assembly-Referenz
Am im Forum: GUI: WPF und XAML

Hallo!

Ich programmiere gerade ein WPF UserControl, welches in einer fremden Anwendung eingebunden werden soll.

Aus den Anforderungen der Anwendung hat sich folgende Architektur ergeben:
Ein Assembly, welches die BL und das ViewModel beinhaltet.
Ein Assembly, welches das Control beinhaltet.
(ich weiß, dass man BL und ViewModel lieber trennen würde, da aber beides aus 3 bis 6 kleinen Klassen besteht, tut mir das nicht wirklich weh).

Für die Anwendung ist es vorteilhaft, dass die beiden Assemblies sich nicht referenzieren. Soweit funktioniert das auch alles gut.

Das Problem ist nun folgendes:
Mein Control muss ein interface implementieren, welches (z.B.) so aussieht:


interface IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { }
  public void OnExecuted(ExecutedRoutedEventArgs e) { }
}

In den EventArgs steht dann jeweils über die OriginalSource der Name des Buttons.

Jetzt würde ich gerne an dieser Stelle quasi ein Command aus dem ViewModel fragen nach CanExecute bzw. in die Execute aufrufen. Also


class MyViewModel {
  public ICommand OkCommand {get; private set;}
}

class MyControl : IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { 
    
    if (e.OriginalSource.Name == "Ok"){
        MyViewModel viewModel = DataContext as MyViewModel; //GEHT NICHT!!
        e.CanExecute = viewModel.OkCommand.CanExecute(null);
    }
  }
}


Aber ich kann den DataContext ja nicht auf das spezifische ViewModel casten, weil ich keine Referenz auf das Assembly habe.

Gibt es nun einen "eleganten" Weg, dass ich mir in XAML dieses Command über DataBinding hole, oder muss ich das im CodeBehind über Reflection machen?

Vielen Dank!

Thema: gleichnamige Methoden (static,Instanz) mit identischer Signatur
Am im Forum: Grundlagen von C#

Zitat
Statische Methoden sind solange praktisch, solange du nicht versuchst threads zu verwenden, dann kann es knifflig werden.

Das ist so falsch. Das Problem tritt bei statischen Variablen auf. Gegen Statische Methoden, welche nur Parameter und lokale Variablen haben, spricht nichts. Im gegenteil halte ich das für eine sehr einfache Möglichkeit, Threadsicherheit zu erreichen.

Ist dann zwar quasi prozedurale Programmierung als OOP, aber wenn es zum Problem passt (mathematische Algorithmen o.Ä.) völlig OK.

Es ist sogar so, dass - wenn ich ein Objekt habe, welches einen Algorithmus durchführt und dabei seinen inneren Zustand temporär verändert - ich sehr gerne statische Hilfsmethoden schreibe die eine Instanz erzeugen, den Algorithmus ausführen, die Instanz wegwerfen und das Ergebniss zurückgeben. Quasi um Threadsicherheit zu garantieren.


Zusammenfassend zum Thema Threads:
Trivial threadsicher sind Methoden, die nur Parameter und Lokale Variablen verwenden.

Gefährlich sind immer äußere Zustände. Bei normalen Objekten kann mann dann verschiedene Instanzen anlegen, bei statischen, nicht readonly Variablen hat man ein Problem.....

Thema: Get- und Set-Accessoren: Guter Stil - Schlechter Stil
Am im Forum: Rund um die Programmierung

Getter und Setter verletzen das OOP-Prinzip genauso wie get und set Methoden. Also erstmal garnicht, bei extensivem gebrauch bekommt das ganze aber einen Geschmack.

Du kannst in einem Getter etwas berechnen, also nur weil es ein Getter gibt muss dahinter noch lange kein Feld stehen. Insofern Kapselt ein Getter. Auch ein Setter muss nicht unmittelbar in ein Feld schreiben, könnte also z.B. einen Setter von einem privaten Objekt aufrufen.

Insofern kapseln sowohl Getter und Setter die Implementierung, sind daher guter OOP-Stil.

Ein Problem wird das ganze dann, wenn man - weil es ja so schön einfach ist - aus jedem privaten Feld ein Property macht ung {get; set;} dahinter schreibt. Dann verletzt man die OOP-Prinzipien.

Generell gilt für alles, was public ist: So viel wie nötig, so wenig wie möglich. Das gilt auch für Properties.

Thema: Standardverhalten eines Interfaces in einer Basisklassen implementieren: Ist das ok/sinnvoll?
Am im Forum: Rund um die Programmierung

Ich finde immernoch, dass die meisten Argumente eigentlich den Kern des Problems nicht treffen.

Die abstrakte Basisklasse ist ein Implementierungsdetail, was nach außen nicht bekannt ist. Ich kann es jederzeit ändern.

Wenn nun 8 Klassen von dieser Basisklasse ableiten, für eine neunte passt es nicht mehr, dann implementiere ich halt das Interface direkt. Wenn ich eine Klasse erweitern will und die Basisklasse nicht mehr passt, dann implementiere ich das Interface direkt oder erbe gar von einer anderen Basisklasse.

In all diesen Fällen bekommen die Benutzer des Interfaces das garnicht mit, weil die Entkopplung eben über das Interface stattfindet. Die Basisklasse entspricht eher einer "privaten Vererbung" aus dem C++-Umfeld.

Daher würde ich das weiterhin machen und mich um ggf. auftretende Probleme erst später kümmern. Denn Probleme mit einer Klasse in dieser Architektur können nur dann auftreten, wenn sich die Aufgaben dieser Klasse ändern. Dann muss ich sie sowieso anfassen. Und die Entkopplung zu den Verwendungen der Klasse bleibt durch das Interface unverändert.

Thema: Standardverhalten eines Interfaces in einer Basisklassen implementieren: Ist das ok/sinnvoll?
Am im Forum: Rund um die Programmierung

Ich finde das Konzet eigentlich sehr sauber, verwende es selbst sehr gerne.
Du musst nur sicherstellen, dass die Nutzer sich eben nur auf das generelle Interface verlassen und nicht auf Implementierungsdetails der abstrakten Klasse.

Die Seperation of Concerns:

  • Interface stellt das nach außen verbindliche Interface dar.
  • Abstrakte Klasse vermeidet Redundanzen in der Implementierung.

Die abstrake Basisklasse bleibt ein Implementierungsdetail, was du jederzeit entfernen könntest ohne dass die Anwendenden Klassen etwas davon mitbekommen.

Ich halte das Konzept sogar eher für eine Best Practice.

Thema: Welches Client/Server Framework (via Internet, enge Kopplung ok)
Am im Forum: Netzwerktechnologien

Hallo!

Bisher habe ich reichlich Erfahrungen mit GUI-lastigen Desktop-Anwendungen, werden nun aber eine Client/Server-Anwendung entwickeln müssen. Während sich für einige Bereiche mein Bild schon geschärft hat, stocher ich in anderen Ecken noch im Nebel...

Folgendes (fiktives, aber dem Problem nahe kommendes) Szenario.

In einer Universität teilen sich drei Fachbereiche ein Gebäude. Jeder Fachbereich hat im Wesentlichen seine eigenen Räume, aber einige große Hörsäle werden auch gemeinsam genutzt. Es soll nun eine Software entwickelt werden, um die Vorlesungen zu planen. Außerdem sollen Studenten per Internet / Mobile App sich zu anmelde-beschränkten Kursen und / oder Übungen anmelden zu können.

Es gibt folgende Komponenten:

  • Pro Fachbereich einen lokal installierten Planungs-Client, mit dem die Vorlesungen dieses Fachbereichs geplant werden können. Da dieses durch Optimierungsalgorithmen unterstützt wird und recht komplexe Interaktionen benötigt, ist eine Implementierung als HTML im Browser nicht sinnvoll.
  • Einen zentralen Server, auf dem der aktuelle Plan gespeichert ist und mit dem die Planungs-Clients kommunizieren. U.A. muss es z.B. möglich sein, dass ein Planungs-Client einen gemeinsam genutzten Hörsaal für einen gewissen Zeitraum sperrt, um in diesem umzuplanen (Pessimistic Locking). Dieses sollte dann allen anderen Clients instantan angezeigt werden (also muss Push vom Server zum Client gehen).
  • Es kann notwendig sein, dass Client und Server nur über Internet verbunden sind, also die Server-Schnittstelle im Internet steht (Sicherheit ist also wichtig).
  • Es gibt eine Website bzw. diverse Mobile Apps, mit denen Studenten sich zu Übungen / Vorlesungen anmelden können bzw. den vorläufigen Plan sehen.
  • Es soll möglich sein, den Studenten Änderungen für angemeldete Kurse per Push-Nachricht zu senden.


Wie gesagt, das Beispiel ist fiktiv, kommt aber unserem Praktischen Problem recht nahe und ich muss jetzt nicht einen Roman zur Erläuterung der realen Anwendung schreiben.


Folgende Design-Entscheidungen habe ich bisher getroffen:
  • Die Mobile Apps werden mit HTML5 erstellt, um nicht für iOS/Android/Windows entwickeln zu müssen.
  • Die Kommunikation des Servers zu den Mobile Apps und der Studenten-Website soll über eine REST-Schnittstelle erfolgen. Mir gefällt dafür NancyFX recht gut, zumal ich mit einem ähnlichen Micro-Framework privat schon gute Erfahrungen gemacht habe (Slim unter PHP, obwohl ich ansonsten PHP hasse.....)
  • Ob die Website eine Single Page Application wird oder ich immer den RoundTrip über den Server gehe und HTML ausliefere, weiß ich noch nicht. Haber aber ein ganz gutes gefühl für die Trade Offs
  • Der Planungs-Client wird eine WPF-Desktopanwendung. Diese wird immer zusammen mit dem Server entwickelt, es gibt nur wenige lokale Installationen und der Komfort währen der Planung ist wichtiger als das Rollout.
  • Authentifizierung vermutlich mittels JSON Web Token.


Bei folgendem Punkt bin ich etwas verloren:
  • Wie mache ich bei der Schnittstelle zu den Apps die Push-Nachricht? Ist SignalR dort eine gute Wahl? Quasi dass man als Message sendet "Es gibt was neues, fordere mal folgende Ressourcen an" und dann einen Link mit sendet.

  • Welche Kommunikation zwischen Planungs-Client und Server verwende ich? Die sind eng gekoppelt, müssen niemals an andere Systeme angebunden werden und werden immer zusammen entwickelt. Die Kommunikation kann aber evtl. über Internet stattfinden, sollte also sicher sein.
    --> Mir erschien WCF das Mittel der Wahl, habe aber jetzt viele Warnungen gehört, dass es sehr komplex sei.
    --> Eine REST-Schnittstelle ist eine sehr lose Kopplung. Ist diese nicht hier zu Aufwändig und zu viel Overhead? Zumal dann die Push-Problematik dann nicht gelöst ist, oder auch SignalR?
    --> Remoting wirkt einfacher, soll aber wohl veraltet sein und nur noch aus Kompatibilitätsgründen mitgeliefert werden. Aber für ein neues Projekt
    --> TCP/IP Sockets: Ist halt sehr low level, dafür versteht man vermutlich, was man tut. Aber bekommt man als Netzwerk-Anfänger wirklich die Probleme in den Griff
    --> Eine Messaging Infrastruktur (MSMQ). Aber brauchen wir wirklich Messaging? Gefühlt ist das eher das klassische RPC?


Insbesondere der letzte Punkt ist derzeit schwierig. Es gibt diverse Möglichkeiten, mir sind die Tradeoffs aber nicht klar. Gibt es dazu Meinungen, Tipps oder evtl. sogar Hinweise zu Tutorials / Büchern, wo die verschiedenen Technologien verglichen werden und Guidelines, wann man welche nimmt?


Vielen Dank für Tipps,
Uwe

Thema: DI-Container, LightCore: Instanz von algemeinerem Interface automatisch Resolven
Am im Forum: Rund um die Programmierung

Stimmt, im allgemeinen führt das vermutlich zu Problemen.

Da ich die Kombination von IFoo und IBar ja im voraus kenne, habe ich nun einfach ExtensionsMethods geschrieben.


static void RegisterBar<TBar>() where TBar:IBar {
    builder.Register<IBar, Bar>();
    builder.Register<IFoo, Bar>();
}

Irgendwie habe ich erst versucht, das über ein RegistrationModule zu machen, aber da das später immer im Code konfiguriert wird, kann ich es eigentlich auch direkt per EtensionMethod machen (dennoch ist es interessant, RegistrationModules zu kennen).

Vielen Dank für den Fingerzeig in die richtige Richtung,
Uwe

Thema: DI-Container, LightCore: Instanz von algemeinerem Interface automatisch Resolven
Am im Forum: Rund um die Programmierung

Hallo, der Titel ist etwas blöd, aber in Code ist es leicht zu erklären, was ich suche...


using LightCore;

interface IFoo {
    void DoFoo();
}

interface IBar : IFoo {
    void DoBar();
}

class Bar : IBar {
    public void DoFoo() {}
    public void DoBar() {}
}

class Program {
    public static void Main() {
        var builder = new ContainerBuilder();
        builder.Register<IBar, Bar>();
        var container = builder.Build();
        var foo = container.Resolve<IFoo>();
    }
}

Bei der letzten Zeile fliegt eine Exception. Ist auch klar, weil kein IFoo registriert ist. Allerdings kennt der Container ja ein IBar und weiß, dass das auch ein IFoo ist. Gibt es eine Möglichkeit, dass das automatisch aufgelöst wird?

Was geht (mir aber nicht so gut gefällt) ist


builder.Register<IBar, Bar>();
builder.Register<IFoo, Bar>();

oder


builder.Register<IBar, Bar>();
builder.Register<IFoo>(c => c.Resolve<IBar>());

Mir ist das ganze deshalb wichtig, weil ich ein Framwork entwickel, welches dann von anderen verwendet wird. Innerhalb des Framworks will ich (aus Kapeselungsgründen) möglichst spezialisierte Interfaces durch die Gegend reichen, nach außen will ich aber für den Benutzer meines Frameworks die Konfiguration des DI Containers möglichst einfach halten.

Viele Grüße und vielen Dank,
Uwe

Thema: WinForms-ComboBox in WPF -> Bildschirm geht aus
Am im Forum: GUI: WPF und XAML

Hallo!

Ich habe das Programm (ThinkPad T410s) bisher nur auf meinem Rechner laufen lassen, kann also einen Fehler im Grafiktreiber nicht ausschließen. Die Benutzerkontensteuerung (musste erst nachschauen, was UAC ist...) habe ich aktiviert, wäre auch eine Idee...

Ich versuche mal ein Minimalbeispiel zu konstruieren, in dem der Fehler auftritt. Habe aber aus diversen Gründen derzeit quasi keine Zeit mehr, werde mich dann in ein oder zwei Wochen nochmal melden...

Schonmal vielen Dank für die Ideen.

Viele Grüße,
Uwe

Thema: WinForms-ComboBox in WPF -> Bildschirm geht aus
Am im Forum: GUI: WPF und XAML

Nein, der Titel ist nicht irreführend. Und ja, ich bin immernoch etwas fassungslos...

Ich habe reproduzierbar folgendes Problem:
Ein eigenes kompliziertes WinForms-UserControl, welches eine ComboBox beinhaltet. Dieses ist eingebunden in eine WPF-Form.

Wenn ich mit der Maus über die WinForms-ComboBox komme, geht kurz der Bildschirm aus (so als wenn man einen externen Monitor / Beamer anschließt und der Rechner versucht, seine Auflösung anzupassen). Bewegte ich die Maus in der ComboBox ist alles ok, solange bis ich die Maus aus der ComboBox rausbewege, dann tritt dasselbe Problem auf.

Das Problem ist unabhängig von Externer Monitor angeschlossen (digial oder analog oder nur Laptop), und Benutzung der Maus oder des Touch-Pads.

Ich hatte dasselbe Control (intern mit etwas anderem Docking/Anchor/AutoSize) auch schon vorher in WPF und es lief einwandfrei...



Da ich perspektivisch die Form eh auf WinForms migrieren soll (soll in eine WinForms-Anwendung eingebaut werden und dann lohnt WPF nur für das Fenster nicht mehr) lässt sich das Problem für mich leicht umgehen.

Aber aus Interesse: Hat schonmal jemand ähnliches gehabt?

Viele Grüße,
Uwe

Thema: MVVM: INotifyPropertyChanged im Model -> unsauber?
Am im Forum: Rund um die Programmierung

Also IMHO wird es falsch, wenn Model-Klassen gegenseitig auf INotifyPropertyChanged hören müssen und dann anhand des Strings erkennen, Was sich nun geändert hat.

Daher habe ich folgende Fausregel:
Existiert eine komplexe Domain Logic, dann sollte das Modell möglichst sauber sein und kein INotifyPropertyChanged implementieren.

Ist die Anwendung eine eher dünne Aufbereitung von Daten ohne komplizierte Domain-Logic, spare ich mir das doppeln aller Daten in Model und ViewModel, implementiere im Model das INotifyPropertyChanged und implementiere nur dann ViewModel-Klassen, wenn diese über das Model hinausgehende Daten halten müssen.

Thema: PostSharp "optional" hinzufügen
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Habe gerade noch folgenden Link gefunden:
Applying aspects to 3rd party assemblies using PostSharp

Thema: PostSharp "optional" hinzufügen
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo!

Ich habe eine komplexere GUI-Komponente entwickelt, die bei uns im Haus oft verwendet wird. Leider treten dort auch manchmal Fehler auf, so dass ich gerne mittels Tracing den Ablauf vor Auftreten des Fehlers feststellen möchte.

Um nicht den ganzen Code zu verschmutzen, dachte ich, dass sei ein gutes Anwendungsfeld für PostSharp (meine erste Berührung mit AOP).

Wir arbeiten bei uns an unterschiedlichsten Projekten und haben unterschiedliche, frei konfigurierbare Entwicklungsumgebungen. Insbesondere wird sicherlich nicht jeder, der meine Komponente verwendet, PostSharp installieren wollen. Auch ist dieses Logging nicht überall sinnvoll.

Daher meine Frage: Kann man sowas in der Art gestalten, dass es z.B. 3 Projekte/Assemblies gibt:

MyLib.Core
MyLib.UnitTest
MyLib.Aspects

Leute, die das ganze verwenden, brauchen nur MyLib.Core (was idealerweise auch so übersetzbar ist)
Als Entwickler habe ich halt noch die UnitTests (und dementsprechend eine Abhängigkeit auf NUnit) und die Aspects (und die Abhängigkeit auf PostSharp).

Bei UnitTests funktioniert das gut: Der eigentliche Produktivcode weiß nichts, über deren Existenz. Bei den Aspects mit PostSharp habe ich vergleichbares nicht hinbekommen.

Was ich möchte: MyLib.Core soll über PostSharp nichts wissen und ohne PostSharp funktionsfähig kompilierbar sein. Aber ich möchte in einem zusätzlichen Build-Step (oder einer anderen Build-Konfiguration) die Möglichkeit haben Logging mittels PostSharp einzuweben.

Geht sowas? Ist AOP der falsche Ansatz?

Viele Grüße,
Uwe

Thema: Coding Styles Horror
Am im Forum: Smalltalk

Ich glaube, das geht kürzer (single threaded Anwendung mit .NET 3.5);


int _value;

public int Value {
    get 
    {
        lock(this)
        {
            try
            {
                return _value;
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
    }
}

Thema: DataGridTemplateColumn für verschiedene DataSource
Am im Forum: GUI: WPF und XAML

Hallo!

Ich habe mir für ein WPF DataGrid ein DataTemplate für die Columns erstellt. Jetzt möchte ich für zwei Properties CustomA und CustomB eine DataGridTemplateColumn mit diesem Template anwenden.

Allerdings kann ich irgendwie dem Template keine DataSource mitgebe, d.h. ich muss im Template selbst schon an CustomA oder CustomB binden (und kann nicht relativ dazu anfangen).

Ich vermute, dass ich als neuling, da ein Teil des Konzepts noch nicht verstehe.

PS: Ich nutze aus verschiedenen Gründen noch das WpfToolkit und .NET 3.5

Vielen Dank,
Uwe

Thema: Fehler in GetHashCode im Framework?
Am im Forum: Rund um die Programmierung

Die GetHashCode-Methode von Structs ist IMO standardmäßig Fehlerhaft:

Aus ValueType.cs


        /*=================================GetHashCode==================================
        **Action: Our algorithm for returning the hashcode is a little bit complex.  We look
        **        for the first non-static field and get it's hashcode.  If the type has no
        **        non-static fields, we return the hashcode of the type.  We can't take the 
        **        hashcode of a static member because if that member is of the same type as
        **        the original type, we'll end up in an infinite loop. 
        **Returns: The hashcode for the type. 
        **Arguments: None.
        **Exceptions: None. 
        ==============================================================================*/

Der Kommentar ist aber falsch. Eine Korrektur steht in Why is ValueType.GetHashCode() implemented like it is?
Zitat
The actual implementation of ValueType.GetHashCode() doesn't quite match the comment. It has two versions of the algorithm, fast and slow. It first checks if the struct contains any members of a reference type and if there is any padding between the fields. Padding is empty space in a structure value, created when the JIT compiler aligns the fields. There's padding in a struct that contains bool and int (3 bytes) but no padding when it contains int and int, they fit snugly together.

Without a reference and without padding, it can do the fast version since every bit in the structure value is a bit that belongs to a field value. It simply xors 4 bytes at a time. You'll get a 'good' hash code that considers all the members. Many simple structure types in the .NET framework behave this way, like Point and Size.

Failing that test, it does the slow version, the moral equivalent of reflection. That's what you get, your KeyValuePair<> contains references. And this one only checks the first candidate field, like the comment says. This is surely a perf optimization, avoiding burning too much time.

Dieser Kommentar wirkt plausibel, wie folgendes Beispiel zeigt:


using System;

struct MyObjStruct {
    public object x;
    public object y;
}

struct MyIntStruct {
    public long x;
    public long y;
}


public class Program {
    static object x = new object();
    static object y1 = new object();
    static object y2 = new object();

    public static void Main() {
        var os1 = new MyIntStruct { x = 1, y = 3 };
        var os2 = new MyIntStruct { x = 1, y = 4 };
        Console.WriteLine(os1.GetHashCode() == os2.GetHashCode()); //False

        var is1 = new MyObjStruct { x = x, y = y1 };
        var is2 = new MyObjStruct { x = x, y = y2 };
        Console.WriteLine(is1.GetHashCode() == is2.GetHashCode()); //True
    }
}


Nun schauen wir uns mal die Equals-Methode aus ValueType.cs an


        public override bool Equals (Object obj) { 
            BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)"); 
            if (null==obj) {
                return false; 
            }
            RuntimeType thisType = (RuntimeType)this.GetType();
            RuntimeType thatType = (RuntimeType)obj.GetType();
 
            if (thatType!=thisType) {
                return false; 
            } 

            Object thisObj = (Object)this; 
            Object thisResult, thatResult;

            // if there are no GC references in this object we can avoid reflection
            // and do a fast memcmp 
            if (CanCompareBits(this))
                return FastEqualsCheck(thisObj, obj); 
 
            FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 
            for (int i=0; i<thisFields.Length; i++) {
                thisResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);
                thatResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(obj, false);
 
                if (thisResult == null) {
                    if (thatResult != null) 
                        return false; 
                }
                else 
                if (!thisResult.Equals(thatResult)) {
                    return false;
                }
            } 

            return true; 
        } 



Fazit: Sind alle Member ValueTypen und können ohne Padding aligned werden, dann wird sowohl für Equals als auch für GetHashCode das Bitmuster verwendet. Ansonsten werden die GetHashCode() des ersten Member und die Equals() aller Member aufgerufen.

Testen wir das:


using System;


struct MyDifference {
    public int x;
    public int y;

    public override bool Equals(object obj) {
        if (!(obj is MyDifference)) return false;
        var other = (MyDifference) obj;
        return x - y == other.x - other.y;
    }

    public override int GetHashCode() {
        return x - y;
    }
}



struct MyObjStruct {
    public MyDifference x;
    public object y;
}



struct MyLongStruct {
    public MyDifference x;
    public long y;
}



public class Program {
    public static void Main() {
        var y = new object();

        var md1 = new MyDifference {x = 5, y = 2};
        var md2 = new MyDifference {x = 6, y = 3};
        Console.WriteLine("Equals myDiff: " + md1.Equals(md2));
        Console.WriteLine("HashCd myDiff: " + (md1.GetHashCode() == md2.GetHashCode()));

        var os1 = new MyObjStruct {x = md1, y = y};
        var os2 = new MyObjStruct {x = md2, y = y};
        Console.WriteLine("Equals objStruct: " + os1.Equals(os2));
        Console.WriteLine("HashCd objStruct: " + (os1.GetHashCode() == os2.GetHashCode()));

        var ls1 = new MyLongStruct {x = md1, y = 9};
        var ls2 = new MyLongStruct {x = md2, y = 9};
        Console.WriteLine("Equals longStruct: " + ls1.Equals(ls2));
        Console.WriteLine("HashCd longStruct: " + (ls1.GetHashCode() == ls2.GetHashCode()));
    }
}

Zu erwarten:
Für die MyDifference müsste beides True ergeben.

Für die MyObjStruct müsste per Reflection sowohl Equals als auch GetHashCode (für das erste Feld) aufgerufen werden, also beide male True ausgegeben werden.

Für die MyLongStruct müssten die Bitmuster verwendet werden (also weder GetHachCode noch Equals aufgerufen werden), und beide male False ausgegeben werden.


Die Ausgabe ist aber

Equals myDiff: True
HashCd myDiff: True
Equals objStruct: True
HashCd objStruct: False
Equals longStruct: True
HashCd longStruct: False

Also ist, obwohl MyDiff eine valide GetHashCode und Equals anbietet, die Implementierung von GetHashCode sowohl für MyObjStruct als auch für MyLongStruct falsch, weil Equals True ergibt und GetHashCode false ist.

Im Debugger sieht mann, dass sowohl by MyObjStruct.Equals() als auch bei MyLongStruct.Equals() die MyDifference.Equals() aufgerufen wird, hingegen in keinem der GetHashCodes die GetHashCode der MyDifference.

Ich habe das auf Win7 64 bit, Vs2010 kompiliert als .NET 4.0;

Das Ergbnis ändert sich nicht, wenn man im MyLongStruct das y durch ein int ersetzt. Es ist sowohl für int y als auch für long y unabhängig vom Kompilieren als x64 oder x86.

Auch das steht eigentlich in StackOverflow
Zitat
One more excruciating detail: the fast version has a bug that bytes when the structure contains a field of a type decimal. The values 12m and 12.0m are logically equal but they don't have the same bit pattern. GetHashCode() will say that they are not equal.

Thema: Eigenentwickeltes C-Programm startet nicht mehr
Am im Forum: Rund um die Programmierung

Also ein C-Programm mit .NET und der C++ Redistributable......

Welche Sprache habt ihr denn nun verwendet? C#, C++ oder C? Oder eine Mischung?
Bei C# werdet ihr .NET brauchen, bei C++ oder C könnte das Redistributable helfen.

Ein beliebter Fehler ist es, bei C oder C++ gegen die Debug-Version zu linken, dann nützt das Redistributable nichts, sondern man braucht gleich Visual Studio

Ansonsten könnte im Ereignismonitor von Windows ein Hinweis stehen.

Mehr gibt meine Glaskugel im Moment nicht her.

Thema: pInvokeStackImbalance / NetFx40_PInvokeStackResilience funktioniert nicht...
Am im Forum: Rund um die Programmierung

Zitat
Warum versuchst du nicht die Fehler zu beheben, anstatt sie nur auszublenden?

Weil sowohl das Managed Assembly als auch die aufgerufene Unmanaged-DLL nicht von uns, sondern von einem Projektpartner kommt und wir auch keine Sourcen davon haben... Wir greifen von außen nur über die Managed-DLL darauf zu.

Wir werden aber Montag mal Kontakt zu dem Partner aufnehmen.

Thema: pInvokeStackImbalance / NetFx40_PInvokeStackResilience funktioniert nicht...
Am im Forum: Rund um die Programmierung

Als Ergänzung:

Ich habe in demselben Programm zu beginn man eine anderen DLL mit falscher Calling Convention aufgerufen. Ob er an der stelle mit pInvokeStackImbalance abbricht, hängt in der Tat von dem Wert von NetFx40_PInvokeStackResilience ab.

Isofern scheint die andere pInvokeStackImbalance zwar bei .NET 3.5 ignoriert zu werden, nicht aber bei .NET 4.0 mit NetFx40_PInvokeStackResilience.

Bin langsam echt ratlos...

Thema: [erledigt] DataSource einer ComboBox ändern?
Am im Forum: GUI: WPF und XAML

Habe jetzt die folgende Lösung:


class Base {
     public string Name { get; set; }
}

class Foo : Base { }
class Bar : Base { }

public ObservableCollection<Foo> Foos { get; private set; }
public ObservableCollection<Bar> Bars { get; private set; }
public IEnumerable<Base> References { get; private set; } //Wirft PropertyChangedEvent

Dann kann ich die Foos und Bars den References zuweisen (weil IEnumerable Kovariant ist), beim Binding wird das aber Anscheinend über Reflection aufgelöst, so dass auch bei References auf CollectionChanged-Events reagiert wird.

Dennoch bleibt die Typsicherheit bei Foo und Bar erhalten.

Selbst wenn Foo und Bar nicht von Base ableiten, könnte man References vom Type IEnumerable (nicht generisch) oder object definieren.

Thema: pInvokeStackImbalance / NetFx40_PInvokeStackResilience funktioniert nicht...
Am im Forum: Rund um die Programmierung

Ich portiere gerade eine Anwendung von WinForms auf WPF und gleichzeitig von .NET 3.5 auf .NET 4.0

Jetzt bekomme ich in einem Assembly, welches ich aber nicht ändern kann, ein pInvokeStackImbalance. Recherche ergab, dass dieses üblicherweise auf eine falsche Calling Convention zurückzuführen ist. Bis .NET 3.5 wurde sowas automatisch behoben, ab .NET 4.0 kommt ein Fehler.

Laut MSDN <NetFx40_PInvokeStackResilience> Element kann man durch

<NetFx40_PInvokeStackResilience enabled="1"/>
in der app.config das alte Verhalten erzwingen.

Bei mir funktioniert das aber nicht....

Hat jemand Ideen? Jetzt weiß ich nicht, ob das trotz dieser Info schief geht, oder ob er die garnicht erst erkennt / einliest.

Bin ziemlich ratlos und für jedne Tipp dankbar.

Thema: [erledigt] DataSource einer ComboBox ändern?
Am im Forum: GUI: WPF und XAML

Ok, wenn ich dich richtig verstehe, verwende ich statt

 
public ObservableCollection<Foo> Foos { get; private set; }
public ObservableCollection<Bar> Bars { get; private set; }

dann


public ObservableCollection<Base> Foos { get; private set; }
public ObservableCollection<Base> Bars { get; private set; }

und kann diese dann dem Property Names zuweisen.



Eigentlich ziemlich offensichtliche Lösung (muss wohl auf dem Schlauch gestanden haben), allerdings zu dem Preis, dass ich in dem ViewModel typsicherheit verliere.

Thema: [erledigt] DataSource einer ComboBox ändern?
Am im Forum: GUI: WPF und XAML

Also erstmal: Mit Optics geht es....


        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                    switch (_refType) {
                        case RefType.BarType:
                            Names = ExpressionObserver.Execute(this, t => t.Bars.Select(x => x.Name)).Cascade();
                            break;
                        case RefType.FooType:
                            Names = ExpressionObserver.Execute(this, t => t.Foos.Select(x => x.Name)).Cascade();
                            break;    
                    }
                }
            }
        }



Die Lösung mit der Polymorphie ist mir noch nicht klar...


    class Base {
        public string Name { get; set; }
         
    }

    class Foo : Base { }

    class Bar : Base { }

Aber was ist nun das Property Names? Ein ObservableCollection<Base>? Da kann ich dann zwar einzeln Foos oder Bars rein tun, aber doch niemals die ganze Liste zuweisen (ist leider nicht Kovariant). Wenn ich aber nur einzelne Werte hinzufüge, muss ich wieder händig auf das Hinzufügen neuer der Foos und Bars reagieren.

Thema: [erledigt] DataSource einer ComboBox ändern?
Am im Forum: GUI: WPF und XAML

Hallo!

Folgendes Problem (ViewModel):


    class Foo {
        public string Name { get; set; }
    }

    class Bar {
        public string Name { get; set; }
    }

    public enum RefType {
        FooType,
        BarType
    };

    class ViewModel : INotifyPropertyChanged {
        RefType _refType;

        public ObservableCollection<Foo> Foos { get; private set; }
        public ObservableCollection<Bar> Bars { get; private set; }

        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                }
            }
        }

        //.......
    }


Jetzt binde ich eine ComboBox an die Foos, eine ComboBox an die Bars und eine an den RefType. Klappt alles.

Nun möchte ich noch eine weitere ComboBox, in der folgendes steht:
Wenn RefType==FooType, soll die ComboBox die Namen aller Foos enthalten. Wenn RefType==BarType, soll die ComboBox die Namen aller Bars enthalten.

Allerdings können sich die Collections Foos und Bars zur Laufzeit ändern. Wären diese statisch, würde ich im setter von RefType eine Collection setzen, und die ComboBox an diese binden:


        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                    switch (_refType) {
                        case RefType.BarType:
                            Names = Bars.Select(x => x.Name).ToArray(); break;
                        case RefType.FooType:
                            Names = Foos.Select(x => x.Name).ToArray();
                            break;    
                    }
                }
            }
        }

        IEnumerable<string> _names;
        public IEnumerable<string> Names {
            get { return _names; }
            private set {
                if (Names != value) {
                    _names = value;
                    RaisePropertyChagend("Names");
                }
            }
        }

Dann bekomme ich aber nicht mit, wenn ein neuer Foo bzw. Bar hinzugefügt wird.
Ich habe schon Optics entdeckt, was vermutlich das Problem lösen könnte (noch nicht probiert).


Gibt es eine im .NET-Framework enthaltene Lösung dafür?

Vielen Dank,
Uwe

Thema: WPF UserControl ViewModel Architekturfrage
Am im Forum: GUI: WPF und XAML

Ich scheine noch zu sehr in Windows-Forms zu denken.

Dort habe ich immer verschiedene Controls bzw. UserControls gehabt, die nach außen hin eine möglichst schlanke Schnittstelle haben und ihre komplette Logik im inneren verbergen.

Ich wollte das nun in WPF ähnlich machen.

Wenn ich euch aber richtig verstehe, ist das der falsche Ansatz. Stattdessen sollte ich versuchen, relativ lose gekoppelte View Models mit schlanker Schnittstelle Zwischeneinander zu erzeugen. Dann Controls, welches ausschließlich mittels DataBinding zum DataContext an diese ViewModels gebunden werden? Diese können dann ggf. mittels Templates sogar automatisch erzeugt werden?


Übrigens Danke für den Hinweis mit dem Content Presenter. Den kannte ich bisher noch garnicht.

Wie gesagt: WPF- und MVVM-Anfänger...

Thema: WPF UserControl ViewModel Architekturfrage
Am im Forum: GUI: WPF und XAML

Habe das nun mal durchgelesen und auch im Wesentlichen verstanden.

Allerdings ist IMHO meine Frage dort nicht beantwortet. Vielleicht kann ich sie nochmal konkretisieren:

Ich habe ein UserControl, welches aus anderen Controls zusammengesetzt ist. Die Schnittstelle nach außen ist schlank (ein Property), intern können komplexere Zustände angenommen werden.
Es gibt verschiedene solche Controls, die nach außen dieselbe Schnittstelle haben.

Ich möchte die gerne in der Art verwenden


<MyControl1 Solution="{Binding Solution}" />
<MyControl2 Solution="{Binding Solution}" />
<MyControl3 Solution="{Binding Solution}" />

Dafür müssen diese Controls ja ein DependencyProperty "Solution" haben.

Mir ist nicht klar, wo die (etwas) komplexere Logik der einzelnen Controls abläuft. In den CodeBehind-Dateien derselben? In einem eigenen ViewModel?

Ich vermute, es müsste ein eigenes ViewModel sein. Muss dieses ViewModel dann auch nach außen bekannt sein (fände ich unschön), oder wie kann ich das Property "Solution" (was ja ein DependencyProperty ist) so im Control implementieren, dass es nur an das (nur intern bekannte) ViewModel weitergereicht wird.

Vielen Dank,
Uwe

Thema: WPF: Binding zu LINQ Expression
Am im Forum: GUI: WPF und XAML

Zitat
Naja - du musst ja nur die fertige Komponente nutzen und nichts nachimplementieren. Ist dir das wirklich zu einfach?

Nee, das ist schon OK. Ich habe nur immer ein blödes Gefühl, wenn ich eine mächtige Komponente einbinde um etwas zu lösen, von dem ich vermutet hätte (aber nicht weiß), ob das auch mit .NET Boardmitteln einfach geht.

Plakativ gesagt: Wenn ich an einer Stelle die Wahl habe zwischen 10 Zeilen und keiner Abhängigkeit oder hingegen 2 Zeilen und eine Assembly-Abhängigkeit, wähle ich lieber die 10 Zeilen.

Aber wenn es dergleichen wirklich nicht gibt, greife ich auf Bindable LINQ zurück...

Thema: WPF UserControl ViewModel Architekturfrage
Am im Forum: GUI: WPF und XAML

Danke für den Link. Ich habe zwar ewig recherchiert und gelesen, den Artikel aber noch nicht. Melde mich dann morgen wieder, wenn ich ihn gelesen und (hoffentlich) verstanden habe ;-)