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 Christoph Burgdorf
Thema: Mobile Anwendung zur Datenerfassung: Welche Technik als Basis wählen (HTML, WP, PhoneGap, ...)?
Am im Forum: Rund um die Programmierung

Hallo zusammen,

hinter dem buzzword html5 verstecken sich auch APIs zum lokalen Speichern von Daten, die selbst erhalten bleiben, wenn der Browser geschlossen wird. Klar der Windows Mobile 6.5 Browser kann das nicht. Aber vielleicht kann man darauf hoffen, das Opera Mobile 11 noch für Windows Mobile 6.5 rauskommt. Aktuell gibt es leider nur Opera Mobile 10 für WM 6.5 welcher noch keinen localStorage unterstützt.

Das ist das Dilemma. Siehe auch:

Browser with HTML5 localStorage for Windows Mobile 6.5

Gruß

Christoph

Thema: Anwendungsentwickler in Göttingen gesucht (.NET, Mobile Computing, ASP.NET MVC, JavaScript)
Am im Forum: Jobbörse

Wir sind ein Beratungs- und Systemhaus im Bereich Mobile Computing.
Wir bieten in unseren Geschäftsfeldern Lösungen durch Beratung, Integration und individuelle Softwareentwicklung aus einer Hand. Gemeinsam mit starken Partnern in Deutschland und dem europäischen Ausland bedienen wir die hohen Ansprüche unserer Kunden (u.a. Metro Group Logistics, Nestlé Schöller Transport, Lekkerland DE, NL, BE, Edeka Nord, DRK Blutspendedienst Ost).

Wir sind stolz auf unsere ausgeprägte Kompetenz, Flexibilität und höchste Zuverlässigkeit.

Für unser Team in Göttingen suchen wir eine/n Anwendungsentwickler/in.

- Du siehst dich im Einklang mit den Grundwerten der Clean-Code-Developer Initiative(CCD)

- Du bist mit dem .NET Framework in Version 3.5 vertraut ( 4.0 wünschenswert)

- Du schreibst deklarativen Code wie diesen:
Customers.Where(customer =>customer.IsActive).Select(customer => customer.ID)

- Du weißt wie man Code schreibt, der sich automatisiert testen lässt und kennst dich mit mindestens einem
Testing Framework aus (NUnit und Rhino Mocks wünschenswert aber kein Muss)

- Du hast Erfahrung im Umgang mit allgemeinen Entwurfsmustern (z.B. MVC, MVVM, MVP, Strategy, Command)

- Wünschenswert aber kein Muss wäre Erfahrung mit dem Entity Framework oder einer anderen ORM
Technologie

- Wünschenswert wäre zudem Erfahrung im Bereich Webtechnologien:
- ASP.NET MVC
- IIS / Apache
- JavaScript Frameworks (z.B. jQuery, dojo, JavaScriptMVC, KnockOut.js, Backbone o.ä)
- JSON / XML
- Ein Plus jedoch kein Muss wäre zudem Erfahrung in den Bereichen WPF und Silverlight

Wenn du dich vielleicht nicht in allen, jedoch einigen Punkten wiedererkennst und Spaß daran hast weiterhin mit hoch aktuellen Technologien zu arbeiten, bist du genau die/der richtige für uns!

Unser Angebot:
Flexible Arbeitszeiten, flache Hierarchien, ein junges dynamisches Team und abwechslungsreiche Arbeit in hoch-innovativen IT-Projekten in den Bereichen Mobile Computing, Transport und Logistik.

Bitte richte Deine aussagekräftigen Bewerbunsunterlagen unter Angabe des frühestmöglichen Eintrittstermins und Deiner Gehaltsvorstellungen ausschließlich per Email an [email protected].
Für weitere Informationen zu unserem Unternehmen geh bitte auf http://www.dff-solutions.de.

Thema: Parser für Kommandozeilenparameter (CommandLineArguments)
Am im Forum: .NET-Komponenten und C#-Snippets

Hallo Christian,

leider funktioniert es für mich jetzt gar nicht mehr:

Ich führe folgenden Befehl aus:

Console.exe -directory='test'

und erhalte dann diese Exception:


Unbehandelte Ausnahme: System.InvalidOperationException: 'ArgumentStart' expecte
d!
   bei BrainFx.Core.CommandLine.Lexer.DoLexing() in D:\git\utilities\src\BrainFx
.Core.CommandLine\CommandLine\Lexer.cs:Zeile 63.
   bei BrainFx.Core.CommandLine.CommandLineArguments..ctor() 

Gruß

Christoph

Thema: Parser für Kommandozeilenparameter (CommandLineArguments)
Am im Forum: .NET-Komponenten und C#-Snippets

Hi,

die Komponente ist super. Ich bekomme nur leider eine Exception, wenn ich double quotes verwende.

Also:


app.exe -directory="test"

geht nicht. Während


app.exe -directory='test'

funktioniert.

Gruß

Christoph

Thema: WCF: Objekt als Singleton oder Instanz übergeben
Am im Forum: Netzwerktechnologien

Hallo LuckyStrike,

meinst du Logging oder Locking? Ein LockingService als Singleton macht Sinn, da hier ja Status gehalten werden muss, während ich bei einem LoggingService den Bedarf eines zentralen Status nicht sehe.

Gruß

Christoph

Thema: Designfrage typisiertes DataSet
Am im Forum: Rund um die Programmierung

Hallo Jörg,

dein DataTable ist nur ein Daten Transfer Objekt (DTO) und nicht die Datenzugriffsschicht. Das DTO darf schon in allen Schichten bekannt sein (imho). Es muss aber nicht unbedingt sein, dass solltest du deine Datenbank ändern (z.B. MSSQL zu MySQL), dass sich dann alle Schichten mit ändern müssen.

Deine DataTable wird ja idealerweise von einem DataAccessLayer an die Businessschicht zurückgegeben und prinzipiell sollte nur der DataAccessLayer genauere Informationen darüber besitzen, welches RDBMS zu einsetzt.

Anders sieht es natürlich aus, wenn du Grundsätzliches an der Datenstruktur änderst. Bei Strukturellen Änderungen musst du mitunter schon ggf. alle Schichten anpassen.

Gruß

Christoph

Thema: [gelöst] "dynamisches Event" dynamisch hinzufügen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

ich bin mir nicht 100%ig sicher, ob ich dich richtig verstanden habe aber du könntest z.B. dynamisch EventHandler erzeugen und in einer Dictionary ablegen so wie ich das hier im NotificationService gemacht hab:
NotificationService als Erweiterung zu Rainbirds ApplikationServer Beispiel

Gruß

Christoph

Thema: Machen Interfaces für simple DTOs Sinn?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Vielen Dank für die ganzen Antworten!

Zitat von Florian Reischl
Einfaches Beispiel:
EmployeeDTO kann eine Property Picture besitzen (oder bekommen). Ganz abhängig von Use-Case kann es sinnvoll sein diese Bilder entweder direkt zu laden und in die DTOs zu stecken oder (in den meisten Fällen) diese Bilder erst lazy nachzuladen. Wenn ich ein Interface übergebe kann ich eine Proxy-Klasse bauen welche on-demand das Bild lädt.

Ja, das macht bei einem solchen Objekt auch noch Sinn. Aber im konkreten Fall handelt es sich wirklich hauptsächlich um sehr primitive DTOs, die nur einfache Datentypen beherbergen.

Gruß

Christoph

Thema: Machen Interfaces für simple DTOs Sinn?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Danke, das bestätigt meine Ansicht :-)

Thema: Machen Interfaces für simple DTOs Sinn?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Oder ist es schlicht ressoucenschonender, wenn man den Verweis in den Schichten gegen das Interface statt gegen das konkrete DTO setzt?

Thema: Machen Interfaces für simple DTOs Sinn?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo miteinander,

ich bin gerade dabei mich in ein fremdes Projekt einzudenken. Zur Datenübertragung werden hier selbst geschriebene DTOs verwendet. Ich habe bisher immer DataTables als DTOs verwendet.

Jetzt stolpere ich gerade darüber, dass hier zu jedem DTO ein Interface erstellt wird. Inwiefern macht das eigentlich Sinn? Der Sinn eines Interfaces in Bezug auf eine Service Klasse liegt ja auf der Hand, da hier Methoden unterschiedlich implementiert werden können. Was bringt einem das Interface aber in diesem Fall?


public class Kundenart
{
        public string ID
        {
            get { return this._id; }
            set { this._id = value; }
        }

        public string Beschreibung
        {
            get { return this._beschreibung; }
            set { this._beschreibung = value; }
        }
}


    public interface IKundenart : IXmlSerializable
    {
        string ID { get; set; }
        string Beschreibung { get; set; }
    }

Wenn ich einfach nur meine BOs in allen Schichten benutzen möchte, kann ich doch auch eine BusinessObjects Assembly machen, die ich in allen Schichten referenziere. Aber das Interface ist hier doch eigentlich überflüssig oder übersehe ich hier etwas entscheidendes?

Gruß

Christoph

Thema: Wiki auf .Net Basis?
Am im Forum: Smalltalk

Hallo NudelMC,

ich habe bisher von Mindtouch (ehemals DekiWiki) viel Gutes gehört:http://www.mindtouch.com/Products/Download

Gruß

Christoph

Thema: Fehler beim Event-Feuern in IPCChannel
Am im Forum: Netzwerktechnologien

Hallo burkut,

an dieser Stelle möchte ich noch mal den Hinweis auf diesen Thread geben: NotificationService als Erweiterung zu Rainbirds ApplikationServer Beispiel

Gruß

Christoph

Thema: Datarelation erstellen
Am im Forum: Datentechnologien

Zitat
Leider verstehe ich somit aber nicht, was mir dann diese DataRelation bringt, wenn ich über sie an keine Verknüpften Daten komme.

Für eine Master Detail Ansicht mit zwei DataGridViews ist eine DataRelation ja hervorragend geeignet. Nur das Kombinieren zweier DataTables in einem DataGridView ist eben so nicht möglich.

Thema: .Net Remoting Callback Problem
Am im Forum: Netzwerktechnologien

Hallo lord_fritte,

mal ganz konkret zu der Fehlermeldung: In der Standardkonfiguration dürfen bestimmte Typen nicht deserialisiert werden. Dazu zählen unter anderem Delegaten. Daher musst du TypeFilterLevel auf Full stellen, damit die Deserialisierung klappt.

Gruß

Christoph

Thema: DataSet Aktualisierung ausgelöst von Datenbank
Am im Forum: Datentechnologien

Hallo formatter,

so etwas macht man mit einem Application Server. Schau dir dazu am besten diesen beiden Threads an:

Fragen, Diskussion, Kritik zu Projekt ".NET Applikationsserver"
NotificationService als Erweiterung zu Rainbirds ApplikationServer Beispiel

Beim Microsoft SQL Server gibt es auch Server Events, die einen über Änderungen in der Datenbank benachrichtigen können. Bei MySQL gibt es das aber nicht - also Applicationserver!

Gruß

Christoph

Thema: Daten an an eine anderen Forms-Anwendung übergeben und später Ergebnisse abholen
Am im Forum: GUI: Windows-Forms

Hallo PES 4ever,

vielleicht ist das ein guter Zeitpunkt mal auf meinen NotificationService hinzuweisen. Klingt vielleicht ein wenig überdimensioniert, aber falls du dich ohnehin mit Remoting und Events beschäftigen möchtest, empfehle ich dir den Thread mal zu lesen.

NotificationService als Erweiterung zu Rainbirds ApplikationServer Beispiel

Gruß

Christoph

Thema: Kommunikation zwischen zwei Forms wärend Laufzeit mit TCP
Am im Forum: Netzwerktechnologien

Zitat von mrdjoker
Wenn ja, dann ist es ganz einfach, du speicherst eine Referenz von Form2 in Form1.

Bitte nicht ein komplettes Form übergeben. Man übergibt ein DTO (Data Transfer Object). Das kann z.B. eine DataTable sein.

Gruß

Christoph

Thema: Änderungen am DataSet in die Datenbank übernehmen
Am im Forum: Datentechnologien

Zitat von Inuyasha2004
Datenbanksystem: ADO.NET
Nochmal um sicher zu gehen das ich es richtig verstanden habe. Das DataSet beinhaltet eine Kopie der Datenbank beim starten der Anwendung.

Hallo Inuyasha2004,

obwohl dir das jetzt nicht bei deinem eigentlichen Problem hilft, möchte diese Aussage nicht so stehen lassen. Es ist ein häufiger Anfängerfehler, die komplette Datenbank beim Starten der Anwendung einzulesen und im Speicher zu halten. Das funktioniert auch - anfangs sogar sehr gut. Aber diese Lösung skaliert nicht gut. Deine Anwendung braucht zunehmend länger um zu starten und wird in der Bedienung zäher und zäher. Du solltest daher vom Grundsatz immer nur die Daten laden, die du zum jeweiligen Zeitpunkt für die jeweilige Funktion, Formular oder Bericht benötigst.

Nun kenne ich deine Anwendung natürlich nicht und ggf. sagst du, deine DB hat eine feste Größe, die nicht wächst. Dann ist das ok. Da aber viele Anfänger den Fehler machen eine wachsende DB im ganzen beim Start der Anwendung einzulesen, wollte ich an dieser Stelle nochmal darauf hinweisen, dass dies keine solide Lösung darstellt.

Gruß

Christoph

Thema: Versionsverwaltung für eine Person sinnvoll?
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo iced-t89,

das ist absolut sinnvoll auch wenn man nur alleine entwickelt. Alleine schon deshalb, weil du keine Angst mehr haben musst etwas umzuschreiben, weil du jederzeit wieder auf den alten Stand zurück kannst.

Gruß

Christoph

Thema: NotificationService als Erweiterung zu Rainbirds ApplikationServer Beispiel
Am im Forum: Rund um die Programmierung

Ich möchte euch hier einen Ansatz vorstellen, wie man die Komplexität von Remoting Events elegant verbergen und stattdessen auf eine sehr allgemeine und einfache Lösung zurückgreifen kann.

Bevor ich meine Lösung genauer vorstelle möchte ich kurz aufzeigen was „das Problem“ mit Remoting Events ist und warum es meiner Meinung nach Sinn macht den hier beschriebenen Weg zu gehen.

Die Interims Klasse

Wenn man auf klassische Art und Weise versucht ein Event serverseitig zu feuern und clientseitig zu empfangen, stößt man zu allerst auf eine System.IO.FileNotFoundException. Das hat den Hintergrund, dass der Server zugang zu den Metadaten der registrierten Methode haben muss. Da wir aber eine Methode registrieren möchten, die in der Client Assembly liegt und auf dem Server nicht bekannt ist, kommt es zu der genannten Exception. Die Lösung hierfür ist hinlänglich bekannt. Man benötigt eine Interimsklasse, die sowohl auf dem Server als auch auf dem Client bekannt ist. Die Interimsklasse stellt sowohl eine Methode bereit, die im Serverevent registriert wird als auch ein Event, dass wiederum vom Client abonniert werden kann.

Die verschwundene Event Subscription

Haben wir das erste Problem hinter uns gelassen, begegnen wir einer neuen Herausforderung. Ein Objekt, dass von der Remoting Infrastruktur als SingleCall Objekt publiziert wird, zeichnet sich dadurch aus, dass pro Methodenzugriff eine neue Instanz erstellt wird, die sofort nachdem die Methode abgearbeitet wurde, wieder verfällt. Was bedeutet das für unsere Events?

Nehmen wir an wir haben einen ProductService über den wir neue Produkte erstellen und bestehende bearbeiten können. Unsere Service stellt das Event „ProductCreated“ bereit, welches von einer Client Methode abonniert werden kann.

Unsere Clientklasse sieht dann in etwa so aus:


public class MyClient
{
    IProductService _productServiceProxy = null;
	
    public MyClient()
    {
        _productServiceProxy = ServiceFactory<IProductService>.CreateProxy();
        _productServiceProxy.ProductCreated += new EventHandler(ProductCreated);
    }

    public void CreateProduct()
    {
        _productServiceProxy.CreateProduct(new Product());
    }

    private void ProductCreated(object sender, EventArgs e)
    {
        //Do Something
    }
}

Da wie bereits erwähnt pro Methodenzugriff eine neue Instanz erstellt wird, ist unsere EventSubcription nicht nachhaltig. Die Instanz, die die EventSubscription hält lebt ja nur für einen kurzen Moment. Insofern wird die Methode ProductCreated im Beispielcode nie ausgeführt. Die Instanz, die den Methodenzugriff CreateProduct() bedient hat, hält nämlich gar keine EventSubscription mehr im Speicher.

Wie können wir diesem Problem begegnen? Wir könnten unseren ProductService als Singleton veröffentlichen. Das will man aber in der Praxis nicht. Damit unsere Anwendung gut skaliert sollte die Mittelschicht möglichst statuslos implementiert werden. Zudem müssten wir uns plötzlich mit weiteren möglichen Problemen auseinandersetzen. Ein als Singleton veröffentlichtes Objekt muss natürlich threadsicher implementiert werden.
Unser Problem ist also, dass wir die Mittelschicht einerseits statuslos implementieren möchten aber in einem statuslosen Objekt keine EventSubscriptions halten können.

Lösung über einen NotificationService

Helfen kann uns hierbei ein NotificationService dessen einzige Aufgabe darin besteht Events und dessen Subscriber zu verwalten und Events zu feuern. Die eigentlichen Dienste (z.B. ProductService) bleiben auf diese Art und Weise frei von jeglicher Eventlogik und können weiterhin als SingleCall publiziert werden. Am Ende erhalten wir auf diese Weise ein allgemeingültiges Konstrukt, dass die Verwendung von RemotingEvents genauso einfach (oder sogar einfacher) macht als lokale Events.

Ich habe mich in meinem Projekt stark an dem von Rainbird hier im Forum veröffentlichten Anwendungsserver orientiert, weshalb man die hier beschriebene Lösung ohne großen Aufwand als Erweiterung in seinen Anwendungsserver einarbeiten kann.

Am Ende kann unser oben erwähnter ProductService das Event „ProductCreated“ mit diesem simplen Einzeiler feuern:


ApplicationServer.RaiseEvent(„ProductCreated“, EventArgs.Empty);

Unser Client von oben sähe entsprechend so aus:


public class MyClient
{
    IProductService _productServiceProxy = null;
	
    public MyClient()
    {
        _productServiceProxy = ServiceFactory<IProductService>.CreateProxy();
        ApplicationServer.SubscribeEvent(“ProductCreated”, ProductCreated);
    }

    public void CreateProduct()
    {
        _productServiceProxy.CreateProduct(new Product());
    }

    private void ProductCreated(object sender, EventArgs e)
    {
	//Do Something
    }
}

Man sieht: Die Verwendung ist denkbar einfach! Der Service ist konfigurationslos. Das bedeutet, dass ein Event automatisch im Service erstellt wird, sobald ein Client es abonniert. Die Kehrseite der Medaille ist natürlich, dass die Eventnamen untypsiert vorliegen. Der Service stellt allerdings Methoden zur Überprüfung der vorliegenden Events und Subscriptions bereit um einen bei einer etwaigen Fehleranalyse zu unterstützen. Die fehlende Typisierung wiegt für mich jedoch weniger schwer als der Aufwand RemotingEvents ohne einheitliche Komponente zu verwenden. Dies wird noch deutlicher, wenn wir uns im Detail ansehen, wie der Service im Hintergrund arbeitet.

Es folgt nun eine Schritt für Schritt Anleitung um den Anwendungsserver von Rainbird um diesen NotificationService zu erweitern.


1. Erweiterung der Server API um das INotificationService Interface

Dieses Interface muss in Rainbird.Appserver.API zu den anderen Interfaces der allgemeinen Serverdienste (ILockingService, ISecurityService)


public interface INotificationService
{
	void Subscribe(string eventName, EventHandler handler);
		
	void RaiseEvent(string eventName, EventArgs e);
		
	Dictionary<string, int> GetInfo();
}

2. Erweiterung der Server API um die EventWrapper Klasse

Diese Klasse muss ebenfalls in die API. Die eigentliche Callback Methode (vom Client) wird in dieser Klasse verpackt. Diese Klasse ist bedingt, dadurch das sie in der API Assembly liegt sowohl für Server als auch Client zugänglich.


public class EventWrapper : MarshalByRefObject
{     
    public event EventHandler WrapperServerEvent;
            
    public EventWrapper(EventHandler handler)
    {
        WrapperServerEvent += new EventHandler(handler);
    }

    public void WrapperServerEventHandler(object sender, EventArgs e)
    {
        EventHandler wrapperServerEvent = WrapperServerEvent;
                  
        if (wrapperServerEvent != null)
            wrapperServerEvent(this, e);                   
    }
            
    public override object InitializeLifetimeService()
    {
        return null;
    }
} 
3. Erweiterung der statischen ApplicationServer Klasse

Folgendes muss in die statische ApplicationServer Klasse. Das macht die Verwendung am Ende so einfach wie die Verwendung der Datensatzsperrungen.


public static void RaiseEvent(string eventName, EventArgs e)
{
    INotificationService notificationServiceProxy = ServiceFactory<INotificationService>.CreateProxy();
    notificationServiceProxy.RaiseEvent(eventName, e);
}
		
public static EventHandler SubscribeEvent(string eventName, EventHandler handler)
{
    EventWrapper wrapper = new EventWrapper(handler);
    INotificationService notificationServiceProxy = ServiceFactory<INotificationService>.CreateProxy();
    notificationServiceProxy.Subscribe(eventName, wrapper.WrapperServerEventHandler);
			
    return wrapper.WrapperServerEventHandler;
}

4. Implementation des NotificationService

Diese Klasse muss in die Serverassembly (wo auch LockingService etc. liegt). Es handelt sich um den eigentlichen NotificationService den ich auch manuell über RemotingServices.Marshal direkt veröffentliche. Hier passiert schon ein bisschen mehr, weshalb ich das mal ein wenig genauer erklären werde.

Zunächst einmal benutze ich ein Dictionary<string, EventHandler> um die Abos zu speichern. Wenn also beispielsweise zum aller ersten Mal das Event „ProductCreated“ über Subscribe() abonniert wird, erstelle ich einen Eintrag im Dictionary mit der Bezeichnung als Key („productchanged“) und dem übergebenen EventHandler als Value. Wird dieses Event nun noch weitere male aboniert füge ich alle weiteren EventHandler diesem ersten EventHandler im Dictionary hinzu.

Wird eine Subscription mit einem anderen EventNamen eingetragen, wird ein weitere Eintrag im Dictionary erstellt usw. So ergibt sich also die Situation, dass wir pro EventTyp einen Dictionary Eintrag mit n Callback Methoden haben.

Beim Feuern des Events ist außerdem darauf zu achten, dass man „tote Clients“ wieder aus der Invocationlist entfernt. Andernfalls wird der Server auf Dauer immer langsamer. Nun ist es aber so, dass ich die Events asynchron feuere und damit über den ThreadPool abwickeln lasse (BeginInvoke). Das hat sich für mich in der Praxis besser bewährt. Dadurch bekommt man aber von der Exception nichts mit und tote Clients können nicht entfernt werden. Das habe ich umgangen indem ich das eigentliche Delegat nochmals in ein InnerDelegate gewrapped habe. Ich feuere nun das InnerDelegate asynchron und das eigentliche Delegate synchron, sodass ich auf die Exception reagieren und die EventSubscription wieder entfernen kann


public class NotificationService : MarshalByRefObject, INotificationService
{
    private delegate void InnerDelegate(string eventName, EventArgs e, EventHandler eventDelegate);
    private static NotificationService _singleton = null;
    private Dictionary<string, EventHandler> _eventList;
    private object _thisLock = new Object();
         
    private NotificationService()
    {
        _eventList = new Dictionary<string, EventHandler>();
    }
		
    public void Subscribe(string eventName, EventHandler handler)
    {
        lock(_thisLock)
	{							
            eventName = eventName.ToLower();
				
            if (_eventList.ContainsKey(eventName))
            {
                _eventList[eventName] += handler;
            }
            else
            {
                _eventList.Add(eventName, handler);
            }
        }
    }
			
    public static NotificationService Instance
    {
        get
        {
            if (_singleton == null)
                _singleton = new NotificationService();
				
            return _singleton;
        }
    }
		
    public override object InitializeLifetimeService()
    {
        return null;
    }
		
    public void RaiseEvent(string eventName, EventArgs e)
    {			
        eventName = eventName.ToLower();
        OnServerEvent(eventName, e);
    }
		
    public Dictionary<string, int> GetInfo()
    {
        Dictionary<string, int> info = new Dictionary<string, int>();
			
        foreach (KeyValuePair<string, EventHandler> kvp in _eventList)
        {
            info.Add(kvp.Key, kvp.Value.GetInvocationList().Length);
        }
			
        return info;
    }
				
    private void OnServerEvent(string eventName, EventArgs e)
    {
        lock(_thisLock)
        {
            if (_eventList.ContainsKey(eventName) && _eventList[eventName] != null)
            {
                EventHandler eventDelegate = null;
                Delegate[] invocationList = null;
					
                try
                {
                    invocationList = _eventList[eventName].GetInvocationList();
                }
                catch(MemberAccessException ex)
                {
                    throw ex;
                }
					
                if (invocationList != null)
                {
                    foreach (Delegate del in invocationList)
                    {
                        eventDelegate = (EventHandler)del;
                        InnerDelegate innerDelegate = new InnerDelegate(BeginSend);
                        innerDelegate.BeginInvoke(eventName, e, eventDelegate, null, null);
                    }
                }
            }
        }
    }
		
    private void BeginSend(string eventName, EventArgs e, EventHandler eventDelegate)
    {
        try
        {
            eventDelegate(this, e);
        }
        catch (Exception ex)
        {
            _eventList[eventName] -= eventDelegate;
        }
    }
}

Das ist im Prinzip schon der ganze Zauber. Momentan fehlt dem Service leider noch eine Unsubscribe Methode. Für den Client sollte das Stornieren des Abos so einfach sein wie das Abonnieren. Demnach sollte man das Abo mit diesem simplen Einzeiler wieder auflösen können:


ApplicationServer.UnsubscribeEvent(“ProductCreated”, ProductCreated);

Das Kernproblem hierbei ist, das der NotificationService mit der Client Methode ProductCreated nur leider herzlich wenig anfangen kann (deshalb benötigt man ja den Wrapper). Mir schweben zwar bereits zwei Lösungen hierfür vor, jedoch habe ich bisher nicht die Zeit gefunden die Umsetzung weiter zu verfolgen.

Besonderen Dank möchte ich an dieser Stelle noch einmal an die Adresse von Rainbird richten, der mir bei der Umsetzung meiner Idee mit Rat und Tat zur Seite stand.

Über Feedback, Fragen und Anregungen zu der hier gezeigen Lösung würde ich mich sehr freuen.

Gruß

Christoph

Thema: Fehler bei .ValueChanged
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

@D-eath

Man braucht hier ValueChanged gar nicht. Man muss doch bei dem ButtonClick nur den Wert des DateTimePickers abfragen und entsprechend auswerten.

Thema: Fehler bei .ValueChanged
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Skilllord,

da hast du etwas falsch verstanden. ValueChanged ist keine Eigenschaft, die du abfragen kannst, sondern ein Event, das du abonnieren kannst.

Deine Entwicklungsumgebung stellt Events, Eigenschaften, Variablen etc. alle unterschiedliche da, wenn du sie dir über Intellisense anzeigen lässt. Tipp doch mal datetimepicker1, mach dann den Punkt und sieh dir die Liste an, die deine Entwicklungsumgebung für dich öffnet. ValueChanged hat ein ganz anderes Symbol! Da kannst du nix abfragen ;-)

Gruß

Christoph

Thema: Mysql autoincrement - Column 'id' does not allow nulls.
Am im Forum: Datentechnologien

Hallo sbirg,

wenn die ID vom MySQL Server generiert wird, kannst du in der DataColumn als DefaultValue einfach 0 einstellen. Der Server vergibt dann die ID und die DataTable ist besänftigt. Du musst aber die entsprechende ID, die der Server vergibt beim Server abfragen und zurückschreiben. Stichwort: IdentityCommand und RowUpdated Event vom DataAdapter.

Die andere Variante ist dass du vom Client GUIDs erstellen lässt und dir damit diesen Serverroundtrip sparen kannst. Allerdings ist der MySQL Server nicht für die Verwendung von GUIDs optimiert (im Gegensatz zum MS SQL Server).

Gruß

Christoph

Ps.: Ich verwende in X Projekten Variante A und kann damit gut leben. Es gibt aber einige gute Gründe Variante B zu verwenden ;-)

Thema: DataSource eines DataGridViews
Am im Forum: GUI: Windows-Forms

@ErfinderDesRades

Ich habe erst kürzlich ein DataGridView gebastelt, dass eine Live Überwachung von Produktionsaufträgen gewährleistet. Da wird nichts an den Daten im Grid verändert. Die Daten werden nur ausgelesen, verschieben sich, wechseln die Farben etc. Hier habe ich auf eine reine untypisierte DataTable gesetzt. Auch unter anderem deshalb, weil die Daten übers Netzwerk gezogen werden und ich somit einfach schlanker aufgestellt bin :-)

Ich stelle die Sachen auch grundsätzlich lieber im Code als im Designer ein. Aber da hat so jeder seine Präferenz ;-)

Ich gebe dir aber vollkommen recht, dass man mit typisierten DataSets arbeiten sollte, wenn der Fokus darauf liegt, die Daten weiterzuverarbeiten.

Thema: DataSource eines DataGridViews
Am im Forum: GUI: Windows-Forms

Hallo Rainer Wein,

ich würde das mit dem typisierten DataSet jetzt auch nicht zu hoch hängen. Meiner Meinung nach gibt es auch durchaus Situationen in denen der Einsatz einer untypisierten DataTable (auch gänzlich ohne DataSet) Sinn macht.

Wobei ErfinderDesRades sicher recht hat, dass das typisierte DataSet im Grundsatz dem untypsierten vorzuziehen ist. Insbesondere dann, wenn man viel mit den einzelnen Datensätzen arbeiten muss. Wenn man aber nur von irgendwo Daten einliest und in einem Grid anzeigen möchte, ist ein typisiertes DataSet imho nicht unbedingt nötig oder kann die Sache ggf. sogar unnötig verkomplizieren. (Vorsicht: persönliche Meinung!)

Um das von juetho Gesagte nochmal zu unterstreichen, du kannst dir auch ganz simpel eine autarke DataTable vom DataAdapter befüllen lassen. Ganz ohne DataSet.


DataTable myTable = new DataTable();
myDataAdapter.Fill(myTable);

Gruß

Christoph

Thema: Suche zuverlässigen SVN Hoster
Am im Forum: Smalltalk

Hallo,

erstmal vielen Dank für eure Antworten.

@all

Wir wollen eigentlich generell weg von einer VPS + SVN Lösung. Deshalb suchen wir einen reinen SVN Hoster. Uns fehlen schlicht die Ressourcen das alles zu betreuen. Wir sind ein Zwei-Mann Team und haben jetzt schon kaum Zeit uns um sowas zu kümmern. Zudem bieten die reinen SVN Hoster häufig noch sehr coole Features und ein einfaches User Interface.

@pdelvo

Ich verstehe die FAQ von Google so, dass man ausschließlich Open Source Projekte hosten kann und diese auch nicht vor fremden Blicken schützen kann.

@norman_timo

Beanstalk werde ich mir genauer ansehen. Klingt zumindest vielversprechend.

Hat jemand Erfahrung mit www.sliksvn.com oder sonst einem anderen SVN Hoster?

Gruß

Christoph

Thema: Suche zuverlässigen SVN Hoster
Am im Forum: Smalltalk

Hallo Community,

wir möchten uns von unserem eigenen SVN Server trennen und suchen stattdessen einen guten SVN Hoster auf dem wir unsere Projekte künftig platzieren können. Wichtig ist uns eigentlich nur, dass Closed Source Projekte möglich sind und der Hoster zuverlässig ist. Wenn das ganze dann noch halbwegs günstig ist, wär das ein Traum ;-)

Ps.: Ein Wechsel auf git kommt erstmal nicht in Frage.

Gruß

Christoph

Thema: WinForms --> WPF Umstieg einfach?
Am im Forum: GUI: WPF und XAML

@winSharp93

Ich habe mich noch nicht intensiv mit WPF beschäftigt. Nach allem was ich gehört habe bringt WPF wohl schon deutliche Vorteile. Aber gerade weil es, wie du sagst "ein neues Pradigma" ist, finde ich doch schön, wenn man liest, dass man zumindest nichts falsch macht, wenn man jetzt noch auf Windows.Forms setzt. Es gibt halt Situationen in denen man nicht unbedingt die Ressourcen hat sich sofort in eine neue Technik einzuarbeiten.

Allerdings sollte man natürlich auch nicht zu lange damit warten ;-)

Gruß

Christoph

Thema: WinForms --> WPF Umstieg einfach?
Am im Forum: GUI: WPF und XAML

Hallo Tiefseeaffee,

da ich noch nie mit WPF gearbeitet habe, kann ich dir auch nicht direkt weiterhelfen. Ich empfehle dir aber mal diesen Artikel zu lesen.
http://www.heise.de/developer/NET-Oberflaechen-mit-Windows-Forms-oder-WPF--/artikel/141990

Gruß

Christoph