Okay, noch keine Antwort, dass heißt mein Post war zu verwirrend bzw. ungenau. Als meine ersten beiden konkreten Fragen:
Soll ich die Datenübertragung selbst über den WCF Service steuern, oder mir nur Informationen über neue Jobs von der Datenbank via WCF Service holen und dann die Übertragung separat initiieren z.B. durch TcpClient, also den WCF Service gänzlich außen vor lassen?
Kann ich im WCF Service Events definieren, damit der Client benachrichtigt werden kann wenn der Server einen neuen Job für ihn erstellt hat, oder ganz einfach gefragt, was wäre hierfür die beste herangehensweise?
Hallo Liebe Community,
um meine Kenntnisse in C# zu vertiefen, habe ich mir ein kleines Beispiel Projekt ausgedacht, welches ich nun in Angriff nehmen möchte. Im Folgenden ganz grob die Anforderungen:
Im ersten Schritt wollte ich mir ein paar Anregungen holen, wie die grundsätzliche Architektur aussehen soll. Es handelt sich hier um eine Client / Server Anwendung. Das Client-Programm meldet sich beim Server an wenn es gestartet wird. Der Server hält eine Liste aller Clients, wobei neue Clients hinzukommen können, und sich alte Clients abmelden können. Mit der Serveranwendung kann man Jobs erstellen, die man dann an einzelne Clients zuweisen kann. Bei diesen Jobs kann es sich z.B. um große Dateien handeln, die einer Auswertung bedürfen oder um das Auswerten von Messdaten. Eine Datei soll also bspw. zerteilt werden und die einzelne Teile an Clients verteilt werden, die dann damit arbeiten. Wurden die Dateien auf dem Client bearbeitet, so sollen sie wieder an den Server geschickt werden. Der Server sammelt alle Resultate, und man soll überwachen können welche Übertragungen an welche Clients aktiv sind und welcher Job in wie weit fortgeschritten ist. Der Client soll automatisch benachrichtigt werden, wenn ihm ein neuer Job zugewiesen wurde, dann kann er diesen annehmen. Auch Clientseitig sollen Aktionen protokolliert werden und aktuelle Jobs angezeigt werden.
Die GUI spielt dabei eine Nebenrolle, sie soll leicht austauschbar sein, da ich auch mit MVP bzw. MVVP experimentieren möchte. Ich habe mir gedacht, dass ein WCF Service hier die zentrale Rolle spielen soll. Dieser bietet mir eine Facade mit der jeder Client interagieren kann. Die „Server“ Anwendung soll eigentlich hauptsächlich ein Administrations Tool sein, mit welchem ich Jobs anlegen bzw. zuweisen, Statistiken auslesen und aktive Nutzer sehen kann.
Ich habe mir überlegt im Service Methoden anzubieten wie getNewJobs() getAllJobs() updateJob(). Soll ich die Datenübertragung an sich über eine Methode a la startJob() über den Service steuern, oder nur mit getNewJobs() anhand der Datenbankeinträge überprüfen ob neue Jobs für den Client angelegt sind und diese dann über eine direkte Verbindung zum Server (oder zum Rechner auf welchem die Dateien liegen) übertragen. Welche Übertragungsmethode eignet sich am besten für große Dateien mit .NET? Kann ich über den Service Events feuern, wenn z.B. ein Client einen Job via updateJob() aktualisiert hat, dass der Server den entsprechenden Event abonniert hat und eine ListView aktualisiert?
Erfahrung im Software Design habe ich schon, jedoch bin ich hatte ich bisher nur zeitweise mit .NET zu tun. Mir reichen schon ein paar Tipps und Hinweise, ich möchte nur etwas in die entsprechende Richtung geschubst werden 😉
Also ich bin inzwischen selbst auf folgende Methode gestoßen:
Man bindet den winspool Treiber ein
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
Die Abfrage ob ein Drucker Online ist oder nicht sieht dann folgendermaßen aus:
public bool PrinterIsOnline(string PrinterName)
{
bool isOnline = false;
IntPtr hPrinter = new IntPtr(0);
if(OpenPrinter(PrinterName.Normalize(), out hPrinter, IntPtr.Zero))
isOnline = true;
return isOnline;
}
Nach ein paar Versuchen kann ich sagen, dass es wirklich funktioniert. Falls jemand noch Anmerkungen, Kritik hat etc. bitte raus damit! Es funktioniert zwar, doch das dies der gängige Weg ist, wage ich zu bezweifeln.
Viele Grüße
Ein herzliches Hallo an alle,
aktuell befasse ich mich mit der Frage, wie ich am einfachsten erfahren kann, ob ein Netzwerkdrucker erreichbar ist oder nicht? Ganz ohne Dialoge etc. also einfach anhand der Adresse im Netzwerk: \RechnerA\DruckerA
Das ganze soll in einer Assembly verpackt werden und dann auf einem MSSQL Server 2005 eingebunden werden.
Eine Lösung hatte ich schon:
PrintDocument printDocument = new PrintDocument();
printDocument.PrinterSettings.PrinterName = pathToFile;
isOnline = printDocument.PrinterSettings.IsValid;
Jedoch meckert hier der SQL-Server, da diese Lösung auf .NET 1.1 basiert und der möchte doch gerne was von .NET 2.0 😕
Gibt es hierfür eine einfache Lösung?
Viele Grüße
Hallo Peter,
bool genehmigt = (bool)Eval("Genehmigt");
bool.Parse(Eval("Genehmigt"));
und allerhand Variationen in diese Richtung.
Als Fehler spuckt er mir immer "Datenbindungsmethoden wie Eval(), XPath() und Bind() können nur im Kontext eines datengebundenen Steuerelements verwendet werden."
Bin auch schon auf das hier gestoßen, aber irgendwie bringt mich das grade auch nicht weiter 😦
Hallo Leute,
ich geb hier in einer ListView Daten aus. Die ListView ist sortierbar und eine Pagination ist implementiert, das ganze ist mit JQuery nach diesem Tutorial realisiert. Läuft alles Prima, meine egtl. Frage ist wie kann ich den einen Boolwert prüfen. Mit Eval krieg ich die Sachen ja nur ausgegeben, hab es schon mit casts usw. probiert.
Also der Wert "Genehmigt" ist also boolwert gespeichert und es sollen unterschiedliche Links ausgegeben werden, je nachedem welchen Wert "Genehmigt" hat, das würde ich gerne prüfen.
<%
HotelBuchungssystem.Models.BuchungsRepository br = new HotelBuchungssystem.Models.BuchungsRepository();
OverViewListView.DataSource = br.FindAll();
OverViewListView.DataBind();
%>
<asp:ListView ID="OverViewListView" runat="server">
<LayoutTemplate>
<table id="OverViewListView" border="0" cellpadding="0" cellspacing="0" class="data-table">
<thead>
<tr>
<th></th>
<th>
BuchungsID
</th>
<th>
UserID
</th>
<th>
ZimmerID
</th>
<th>
StartDatum
</th>
<th>
EndDatum
</th>
<th>
Kommentar
</th>
<th>
Genehmigt
</th>
</tr>
</thead>
<tbody>
<tr id="itemPlaceholder" runat="server" />
</tbody>
<tfoot>
<tr id="pager">
<td colspan="7" style="border-right: solid 3px #7f7f7f;">
<img src="../../Content/Images/first.png" class="first" alt="First"/>
<img src="../../Content/Images/prev.png" class="prev" alt="Next"/>
<input type="text" class="pagedisplay"/>
<img src="../../Content/Images/next.png" class="next" alt="Next"/>
<img src="../../Content/Images/last.png" class="last" alt="Last"/>
<select class="pagesize">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option selected="selected" value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</td>
</tr>
</tfoot>
</table>
</LayoutTemplate>
<ItemTemplate>
<td><asp:HyperLink Text="Genehmigen" NavigateUrl='<%#"/Buchung/Approve/" + Eval("BuchungsID").ToString() %>' ID="hl1" runat="server"/></td>
<% }
<td><%# Eval("BuchungsID") %></td>
<td><%# Eval("UserID") %></td>
<td><%# Eval("ZimmerID") %></td>
<td><%# Convert.ToDateTime(Eval("StartDatum")).ToShortDateString()%></td>
<td><%# Convert.ToDateTime(Eval("EndDatum")).ToShortDateString()%></td>
<td><%# Eval("Kommentar") %></td>
<td><%# Eval("Genehmigt") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
Hey Leute,
ich hab in meinem asp.net Projekt eine ganz normale Datenbank eingebunden dbxxx.mdf. Nun habe ich einen haufen "Dummydaten" durch testen usw. drin und würde gerne den kompletten Inhalt der DB löschen. Manuelles löschen wäre ja auch möglich, aber dann zählt er mir ja die IDs trotzdem weiter hoch. Hat jemand einen Tipp wie ich den kompletten Inhalt löschen kann und auch alle ID
s wieder von 1 starten?
verwendetes Datenbanksystem: <MS SQL Express 2005>
Okay danke Euch 😃 Mach mich gleich an die Arbeit.
Hey Th69,
gut okay, da könnte ich auf die entsprechende Column abprüfen, das würde aufjedenfall schon mal funktionieren. Ein Problem dabei wäre aber, dass sich alle ListViews auf diesem Form an diesselbe SortierKlasse hängen, dann müsste ich praktisch für die besprochene ListView eine eigene spezielle Klasse erstellen und dann diese anhängen oder?
Gruß
Hey Leute,
wie der Titel schon sagt, will ich eine ListView mit Checkboxen sortieren und zwar ganz einfach bei Click auf die Column nach selektiert bzw. nicht selektiert. In meiner Klasse die für alle anderen Sortiertaktionen für ListViews zuständig ist (aus einem Tutorial von MS) gibt es ja eine Stelle an der die Items verglichen werden
compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
Gut wenn ich hier umstelle auf
compareResult = ObjectCompare.Compare(listviewX.checked, listviewY.checked);
sortiert er mir schonmal die gechecketen bzw. nichtgecheckten richtig. Aber wie kann ich in der Compare Methode unterscheiden wann er wie sortieren soll? Also nach Checkboxen und wann ganz normal nach Zahl bzw. Alphabet. Sorry wenn ich grad ein bisschen auf dem Schlauch stehe.
Gruß
Hey dN!3L,
also es soll z.B. noch möglich sein die Buchung durch einen Admin freizuschalten.
Wenn dies nach einem Tag der Fall ist, dann bringt er mir natürlich einen Fehler wegen (StartDatum < this.minDate), da minDate das aktuelle Datum ist. Nunja ich denke mal das ich mit diesem Validator hier nicht weiterkomme und am besten nur bei Erstellung der Buchung auf valides Datum prüfe, da im nachhinein eh nur bool Werte verändert werden können? Der Validator hier wird ja jedesmal aufgerufen wenn ich das Objekt ändert oder?
PS: Danke nochmal für deinen Role/Membershipprovider damals, das hat mir sehr weitergeholfen 😃
Hey Leute,
bei meiner asp.net mvc Anwendung benutze ich derzeit einen RuleValdiator ala:
public partial class Buchungen
{
public bool IsValid
{
get
{
return (GetRuleViolations().Count() == 0);
}
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
if (StartDatum > this.maxDate || StartDatum < this.minDate)
yield return new RuleViolation("Falsches Start Datum eingegeben.", "StartDatum");
if (EndDatum > this.maxDate || StartDatum < this.minDate)
yield return new RuleViolation("Falsches End Datum eingegeben.", "EndDatum");
if (StartDatum > EndDatum)
yield return new RuleViolation("End Datum muss vor Start Datum sein.", "EndDatum");
}
partial void OnValidate(ChangeAction action)
{
if (!IsValid)
throw new ApplicationException("Fehlerhafte Eingaben. Konnte Daten nicht speichern!");
}
}
Nun habe ich das Problem, wenn ich an einem Objekt dieser Art einen Wert im nachhinein verändern will, greift dieser Validator und spuckt Fehler aus, wegen dieser Datumskontrollen. Hat jemand eine Idee wie ich dies umgehen könnte, wenn ich z.b. nur einen Wert auf true oder false setzen will im nachhinein? Natürlich könnte ich eine Funktion schreiben, die nur bei erstellen des Objektes die Datumswerte prüft, aber ich würde gerne diesen Valditator beibehalten.
Hey,
sorry wenn ich das jetzt nochmal aufrollen muss.
ich würde vermutlich eine statische Klasse machen, die eine Methode zum Anzeigen von Nachrichten zur Verfügung stellst.
Wie übergebe ich denn der statischen Klasse vom MainForm aus die NotifyIcon instanz, sodass ich dann Applikationsweit z.B. Balloontips abschicken kann, oder wird die Insanz direkt in der Klasse erzeugt? Was ja dann wieder gegen eine Statische Klasse spricht.
Hallo Leute,
ich hab da eine kleine Frage. Ich benutze in meiner Anwendung eine TabControl auf der jeweils einzelne UserControls platziert sind. Auf einer Tab hab ich eine ListView, wenn ich dort einen Eintrag selektiere, dann verliert er mir ja den Focus wenn ich den Tab wechsle bzw. wieder zuürckwechsle. Nun meine Frage, gibt es eine einfache Möglichkeit die Selektierung in der Listview beizubehalten, auch bei TabWechsel etc. bis der User von selbst wieder einen anderen Eintrag wählt?
Vielen Dank 😃
Heyho, jap genau kurz nach dem Post hab ich das auch gesehen 😉. Also es funktioniert jetzt so, aber gibt es auch irgendeinen weg, dass man keine Action aufrufen muss? Für jede kleine Sache würde ich dann ja eine Action brauche, also für lock, unlock etc... Ist das der richtige Weg, oder löst man sowas auf andere weise? Sorry für die vielleicht dummen Fragen, aber ich versuche mir gleich am Anfang einen guten Stil anzugewöhnen 😁
Sorry für die späte Antwort, aber bin schon länger nichtmehr dazugekommen 😉. Also dein Membership und Roleprovider läuft super und ich hab auch schon mehrere Methoden implementiert. Allerdings hapert es an ziemlich einfachen Sachen. Ich habe einen AdminController implementiert, welcher dem Admin z.B. ein editieren / freischalten von Usern ermöglicht. Ich lasse alle User auflisten und daneben ist ein kleiner link Unlock / Lock.
<%= Html.ActionLink("Unlock", "Unlock", new { id = user.UserID })%>
Das ist der Link der im AdminController die Unlock Action aufruft
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Unlock(int id)
{
adminRepository.UnlockUser(id);
adminRepository.Save();
return RedirectToAction("UserOverview");
}
Im prinzip weis ich, dass das alles quatsch ist. Ich will einfach wenn ich auf Lock/Unlock klicke, dass er mir in der DB IsApproved auf true setzt und fertig. Also keine eigene View oder sowas, einfach nur den Wert setzen und zurück zur Übersicht.
Hey Leute,
ich wurde heute zum ersten mal mit RegExpressions konfrontiert und da hats natürilch gleich gescheppert 😄.
Ich habe folgenden Ausdruck:
"regex\stuff\datei.txt", line 531: warning 12345: this is a message - this is a message
this is a message
this_is_a_message, "this is a: message",
^
Das folgende Pattern dazu: ^";(.)", line ([0-9]+): (.): .\n.\n.\n.^$ welches auch hervorragend funktioniert, aber logischerweise nur wenn ich den Ausdruck exakt so eingebe, also mit den Leerzeilen und die sind bei jeder Meldung drin, so wie ihr es hier seht.
Gut nun lese ich das Log mit den Meldungen aus mittels readline und speichere jede einzelne Meldung in einer Liste. Die Meldung steht nun natürlich in einer Zeile
"regex\stuff\datei.txt", line 531: warning 12345: this is a message - this is a message this is a message this_is_a_message, "this is a: message",^
und das Pattern funktioniert nichtmehr. Ich habe es soweit geändert -> ^";(.)", line ([0-9]+): (.): (.).^$ und es geht auch "fast". Wenn in der message ein Doppelpunkt auftaucht schneidet er dort nochmal ab, also im Beispiel wäre es "this is a:" und dann als letzte Group nochmal "message".
Hat jemand einen Tipp wie ich das Pattern noch verändern muss, dass er mir bei der message bis zum "^" durchgeht, ohne beim ":" nochmal zu kürzen? Die Meldungen inkl. der Leerzeichen einzulesen wird nicht möglich sein schätze ich mal.
Sehr schön, Problem gelöst. Vielen Dank an alle 🙂
Gruß
Hey Leute,
ich hätte da eine kleine Frage. Angenommen ich hab einen Pfad der so aussieht: C:\OrdnerA\OrdnerB\OrdnerC\
Ich würde jetzt gerne den Pfad kürzen und zwar um den letzten Ordner, also das die ganze Sache praktisch so aussieht: C:\OrdnerA\OrdnerB\
Hinbekommen hab ich die ganze Sache schon, jedoch is das ein ziemliches gefrickel und daher wollte ich jetzt fragen ob es für diese Problematik evtl. eine einfache Lösung gibt bzw. ob jemand einen Tipp hat?
Gruß
WOW, da bin ich jetzt echt baff das du dir so eine Mühe machst wegen mir 😃 Vielen dank ich werd mir die Sache jetzt gleich mal zu gemüte führen 😃
Gruß
Erstmal danke ich Euch für die Antworten 😃 hab schonmal angefangen die angegebenen Links durchzugehen und bin auch schon ein bisschen schlauer 😃
Ich habe mittels PHP schon mehrere derartige Projekte realisiert und ich glaube ich muss mir hier erstmal eine andere Denkweise angewöhnen, sowas wie eine Roleprovider oder Membershiprovider ist mir alles neu, dass hab ich wohl ein bisschen unterschätzt aber ich will mich aufjedenfall durchbeißen (hoffentlich mit Eurer Hilfe).
Ich wollte die Verwaltung der User mittels der aspnet_regsql.exe auf meine übertragen, soweit habe ich auch keine Fehlermeldungen bekommen, jedoch sehe ich in der Datenbank keine neuen Tabellen und bekomme den Fehler
Die gespeicherte Prozedur 'dbo.aspnet_CheckSchemaVersion' wurde nicht gefunden wenn ich einen neuen User anlegen will.
Ich hänge euch mal ein Bild meiner DB Struktur an. Aber das ich bei Registrierung automatisch in Kunden bzw. Administratoren eintrage, kann ich wohl hier vergessen ohne größere Änderungen am Code vorzunehmen. Könnte man hier die Kunden bzw. Admin Tabelle irgendwie mit der automatisch angelegten Tabelle vom Membershipprovider verbinden?
Eine Idee war, das sich jeder User ganz normal registrieren kann und danach kann ein Admin ihn entsprechend freischalten bzw. zuweisen (Kunde oder Admin). Sozusagen werden die von asp generierten Tabellen mit meinen also Kunden / Administratoren verknüpft.
EDIT: Das Problem bzgl. der Usererstellung hat sich erledigt... war nur ein Tippfehler im ConnectionString. Jedoch bekomme ich in meiner DB keinerlei Tabellen angezeigt, nur meine eigens erstellten.
Hey Leute,
ich muss im Rahmen einer Studienarbeit ein Hotelbuchungssystem mit ASP.Net erstellen und da hab ich mir gedacht ich benutze gleich mal das neue MVC Framework dafür. Allerdings hänge ich jetzt schon am Anfang. Für die Anwendung soll es zwei verschiedene Arten von Benutzern geben, einmal "Kunde" und einmal "Administrator", dafür habe ich nun zwei verschiedene Rollen erstellt und ich habe für beide schon entsprechende Tabellen in meiner Datenbank angelegt. Nun müsste ich ja die View für Werte wie Vorname, Nachname usw. anpassen, da ich diese beim registrieren auch gleich mit eintragen will, aber dann müsste ja zusätzlich am Account Controller direkt noch gewerkelt werden?
Das größte Problem vor dem ich stehe, wie bekomme ich denn die Daten in meine eigene DB und nicht in diese automatisch erstellte ASPNETDB.MDF? Laut www.asp.net
If you don’t want to use the ASP.NET SQL Server Setup Wizard, then you can find SQL scripts for adding the application services database objects in the following folder:
C:\Windows\Microsoft.NET\Framework\v2.0.50727
aber irgendwie hab ich derzeit echt keinen Plan wie ich hier weiterkommen soll 🙁 Habe auch gelesen, dass man für sowas einen eigenen Membershipprovider bzw. Roleprovider schreiben muss, aber das wäre für mich als asp.net Anfänger wohl ein absoluter overkill.
ich hoffe ihr habt ein paar Tipps für mich ...
Danke Tobias, haut hin. 👍 🙂
Hey Leute,
ich hab ein kleines Problem. Wenn ich mein Programm starte, dann wird im Konstruktor vom MainForm ein Objekt eines Singletons erzeugt, welchem dann etwas zugewiesen wird. Genaugesagt, im MainForm wird dem Singleton ein StatusStripLabel zugewiesen und gleich nach Start soll von dem UserControl aus dem Label ein Wert zugewiesen werden. Ich weiß, dass diese Lösung wahrsch. sehr sehr dirty ist, aber hat bis jetzt für diesen Zweck funktioniert, nur halt nicht wenn ich im Konstruktor darauf zugreifen will.
Der Wert ist also noch nicht zugewiesen und er will tatsächlich erst auf das Objekt im UserControl zugreifen und erst dann im MainForm das Objekt überhaupt erstellen bzw. das Label zuweisen. Ich hoffe ihr konntet mir soweit folgen, klingt alles sehr komisch ich weiß 😉 Hat nun jemand eine Idee wie ich hier im MainForm das Objekt erzeugen und dann im Konstruktur vom UserControl darauf zugreifen kann unmittelbar nach Start?
public MainForm()
{
InitializeComponent();
Singleton singleton = Singleton.GetInstance();
singleton.Label = Label;
}
public UserControl()
{
InitializeComponent();
Singleton singleton = Singleton.GetInstance();
singleton.Label.Text = "somestuff";
}
Hey Leute,
derzeit befasse ich mich mit Design Patterns und arbeite die Design Pattern Bibel der GoF durch. Wirklich sehr informativ, aber die Übersetzung hat mich schon ein paar mal auf den falschen Pfad gelockt muss ich sagen -> grauenhaft!
www.dofactory.com dürften hier wohl die meisten kennen, aber hat sich schon mal jemand das DesignPattern Framework 3.5 von denen angekuckt? Click
Für 79 $ ist es zu haben und ich bin kurz davor es mir zu kaufen, da ich durch die C# spezifischen Beispiele schneller vorankommen werde denk ich, natürlich in Verbindung mit dem GoF Buch. Hat sich das schon jemand gekauft und nährere Erfahrungen gemacht oder eine Meinung dazu?
Gruß
Danke für deinen Post 🙂 Dann würde es ja egtl. reichen, wenn ich im SettingsProvider ein Setting für "FirstStart" anlege, den Default auf 0 und nach Aufruf der Initialisierungs Routine beim ersten mal den Wert auf 1 setze. Müsste ja dann im Konstruktor vom MainForm jedesmal den Wert prüfen, aber ich glaube das kann man verkraften oder?
Würde es denn Sinn machen das ganze in eine Klasse zu stecken, da sich die Arbeit doch 4-5 Funktionen teilen, die jetzt im Form rumschwirren. Bzgl. der wiederherstellung der Default Settings werde ich dann wohl eine XML mitliefern müssen, mit deren Hilfe man dann die Standard Einstellungen wiederholen kann?
Hallo Leute,
ich hätte mal wieder ein Anliegen bzgl. Settings. Ich hab mich gefragt, ob es irgendwie möglich ist, beim ersten Start der Anwendung eine Art Initialisierung meiner festgelegten Default Settings durchzuführen? (Also das was im SettingsProvider in VS unter "Values" abgelegt wurde)
Beispiel: Der Anwender startet auf seinem Rechner zum ersten mal die Applikation. Das Programm prüft ob die Pfadangaben, die ich vorher in den Default Settings gemacht habe auf dem Rechner so zutreffen (Bei 90% der Anwender trifft das zu), also ob Pfad A / Pfad B (insg. ca. 12 Pfadangaben) vorhanden sind, oder ob er Manuelle Einstellungen vornehmen will. Wenn vorhanden, werden die Einstellungen übernommen, ansonsten kann der User alle Einstellungen selbst vornehmen.
Die Überprüfung ist schon erledigt, jedoch bezweifle ich, dass man prüfen kann ob das Programm zum ersten mal auf dem Rechner ausgeführt wird und gibt es eine Möglichkeit später diese Default Einstellungen wiederherzustellen?
Herzlichen Dank
Super 🙂 Danke für den Tipp, hat geklappt.
Dictionary<string, IBaseSettings> m_Objects = new Dictionary<string, IBaseSettings>();
public IBaseSettings GetSetting(string type)
{
// Wenn noch kein Key anglegt ist dann anlegen und Objekt darin platzieren
if (!this.m_Objects.ContainsKey(type))
{
// Holen des Objekts von der Factory
this.m_Objects.Add(type, this.CreateSetting(type));
IBaseSettings settings = this.m_Objects[type];
return settings;
}
// Wenn schon ein Key existiert dann hol mir das Objekt raus
else
{
IBaseSettings settings = this.m_Objects[type];
return settings;
}
}
// Aufruf erfolgt jetzt so
viewSettings = SettingsFactory.Current.GetSetting("Views");
Geht das so in Ordnung? Hab das so in der Form noch nie gesehen, deswegen hoffe ich, dass diese Vorgehensweise konform ist. Funktionieren tuts jedenfalls prima 😁
Zunächst mal herzlichen Dank für die Antworten 🙂
Also es scheint wirklich so zu sein, dass er mir jedesmal eine neue Instanz von SettingsA erstellt.
public class SettingsFactory
{
static readonly SettingsFactory m_Current = new SettingsFactory();
static SettingsFactory() { }
SettingsFactory() { }
public static SettingsFactory Current
{
get
{
return m_Current;
}
}
public IBaseSettings FactoryMethod(string type)
{
switch (type)
{
case "SettingsA"
return new SettingsA();
case "SettingsB":
return new SettingsB();
default:
throw new ArgumentException("Falscher Settings Parameter: " + type);
}
}
}
Das Singleton an sich müsste so in Ordnung sein meine ich.
Um auch die Settings so Singleton zugreifbar zu machen, müsste die Factory ein Dictionary der erstellten Settings halten und über eine extra-Property offenlegen.
Okay damit kann ich jetzt noch nicht soviel anfangen, aber ich glaub ich weiß ungefähr was du meinst. D.h. jedesmal wen ich ein Settings Objekt erstelle, wird dies in der Dictionary abgelegt und danach hol ich mir das objekt darüber?
Hey Leute,
ich hab ein kleines Problem mit Events. Ich benutze ein Factory Pattern, wobie die Factory noch ein Singleton beinhaltet. Mit dieser Factory stelle ich Settings für unterschiedeliche Reiter zur Verfügung, siehe dieser Thread Click.
Zu jedem ReiterX, gehört ein FormX auf dem man für den entsprechenden Reiter Einstellungen machen kann. Was ich nun will, ist das wenn man auf FormX Einstellungen ändert, sich alle Controls (meist ListView und Labels) aktualisieren.
public interface IBaseSettings
{
void LoadSettings();
void SaveSettings();
event EventHandler SettingsChanged;
}
public class ViewSettings : IBaseSettings
{
public event EventHandler SettingsChanged;
public void LoadSettings()
{
}
public void SaveSettings()
{
// Hier wird jedesmal der Event gefeuert wenn sich was ändert
OnSettingsChanged(EventArgs.Empty);
}
protected virtual void OnSettingsChanged(EventArgs e)
{
EventHandler handler = SettingsChanged;
if (handler != null)
{
handler(this, e);
}
}
}
// Erzeugen einer Instanz im Form wo Einstellungen gemacht werden
IBaseSettings settingsA = SettingsFactory.Current.FactoryMethod("SettingsA");
// Irgendwo im gleichen Form
settingsA.SaveSettings();
// Erzeugen einer Instanz im Form wo Control sich aktualisieren soll, also dieses Konstrukt könnte in beliebig vielen Forms vorhanden sein
IBaseSettings settingsA = SettingsFactory.Current.FactoryMethod("SettingsA");
//Event abonnieren
settingsA.SettingsChanged += new EventHandler(settingsA_SettingsChanged);
private void settingsA_SettingsChanged(object sender, EventArgs e)
{
// Controls aktualisieren
}
Wie würde es nun laufen, wenn ich die Events feuern will auf egal wievielen Forms ich diesen abonniert habe, derzeit funktioniert es so noch nicht. Ich hab schon gestöbert und einiges herumprobiert, aber eine Lösung habe ich bis jetzt noch nicht gefunden. Wird auf den Forms durch das Singleton in der Factory nicht auf dieselbe Instanz zugegriffen, ich schätze hier existieren einfach zwei verschiedene Instanzen? Ich hoffe ihr habt einen Tipp 🙂
Hallo an alle,
wie der Titel schon sagt suche ich ein / zwei gute Bücher zum Thema Softwarearchitektur bzw. Softwaredesign. Das Buch sollte weder für Vollprofis noch für komplette Anfänger sein. Ich hab mir schon ein paar Bücher rausgesucht, wie dieses hier z.B. Effektive Software-Architekturen: Ein praktischer Leitfaden. Vielleicht habt ihr ja noch ein paar gute Tipps.
Gruß
wenn eine datei nciht existiert, dann muss sie auch nciht überschrieben werden.
Whoops, kleiner Schreibfehler von mir sorry 😁
Problem gelöst... Ans einfachste denkt man natürlich immer zum Schluss. Files im entsprechenden Ordner sind alle schreibgeschützt.
Behoben mit
File.SetAttributes(filename, FileAttributes.Normal);
Hey Leute,
ich habe ein kleines Problem wenn ich eine Datei kopieren will.
FileInfo fi = new FileInfo(filename);
fi.CopyTo(filename, newFilename, true);
File.Copy(filename, newFilename);
Bei beiden wird eine UnauthorizedAccessException geworfen, jedoch nur wenn "newFilename" noch nicht existiert, also die Datei überschrieben werden muss. Kann es sein das ich VS erst "Rechte" geben muss da was zu kopieren? Ich benutze VS 2005.
Gruß
Oh mein Gott... Kopf gegen Tisch knall
Das Leben kann so einfach sein... 😁 wenn man sichs nicht selber andauernd schwer machen würde 😁
Wünsche ein schönes Wochenende und danke das du soviel geduld mit mir hast 👍 🙂
Einen wunderschönen guten Morgen und danke für die Antworten 🙂
sagen wir so das war ein "Teil" des Problems 😉
public partial class ReiterA : UserControl
{
// Hier würde ich mir im Form eine Instanz vom Singleton holen
FactorySingleton MyFactory = new FactorySingleton.getUniqueIstance();
// Dann müsste ich ja hier noch das Konkrete Objekt holen, jedoch kennt er hier kein MyFactory Objekt mehr, aber in den einzelnen Events z.B. wie ButtonA_Click schon. Hier müsste ich ja dann in jedem Event in dem ich auf die Settings zugreifen will wieder mit folgendem Konstrukt ein Objekt instanziiern?
Settings reiterA = MyFactory.CreateInstance("ReiterA");
public ReiterA()
{
InitializeComponent();
}
private void ButtonA_Click(object sender, EventArgs e)
{
// Hier will ich auf das Objekt zugreifen
}
private void ButtonB_Click(object sender, EvenArgs e)
{
// Hier will ich auf das Objekt zugreifen
// Müsste aber mit ... reiterA = MyFactory.CreateInstance("ReiterA") neu anlegen?
}
}
Ist also ein ganz triviales Problem, ich steh grad wirklich dicke aufm Schlauch glaub ich X(. Ich will also das Konkrete reiterA Objekt einmal in der Form erzeugen, damit ich in jedem Event etc. darin drauf zugreifen kann. Wenn ich es so mache
FactorySingleton MyFactory = new FactorySingleton.getUniqueIstance();
Settings reiterA = MyFactory.CreateInstance("ReiterA");
bringt er mir bei der Erzeugung von reiterA einen Fehler "Invalid token '=' in class, struct, or interface member declaration"
EDIT: So hats jetzt funktioniert:
static SettingsFactory factoryObject = new SettingsObject();
Settings reiterA = factoryObject.FactoryMethod("reiterA");
Glaub da hat sich mein Hirn mal wieder in den Ruhezustand geschalten......
Ist das so konform? (Ich liebe dieses Wort 😄)
EDIT 2: Allerdings muss ich noch casten hab ich grade gesehen Settings reiterA = (Settings)factoryObject.FactoryMethod("reiterA");
Hey Norman_Timo Vielen Dank für deine Antwort 👍,
so bis jetzt läuft alles, Controls aktualisieren sich wie gewollt bei Änderung. Jedoch habe ich jetzt ein kleines Problem, wenn ich z.B. eine Objekt Instanz innerhalb eines Forms erstellen will, damit ich innerhalb dieses Forms z.B. in jedem Click Event eins Buttons auf dem Form darauf zugreifen kann.
public partial class ReiterA : UserControl
{
// Erzeuge hier das Objekt für den entsprechenden Reiter mit der Factory
SettingsFactory factoryObject = new SettingsObject();
Settings reiterA = factoryObject.FactoryMethod("reiterA");
public ReiterA()
{
InitializeComponent();
}
private void ButtonA_Click(object sender, EventArgs e)
{
// Hier will ich auf das Objekt zugreifen
}
private void ButtonB_Click(object sender, EvenArgs e)
{
// Hier will ich auf das Objekt zugreifen
}
}
Ok das erzeugen des Objekts innerhalb eines Events oder innerhalb des Konstruktors funktioniert einwandfrei, jedoch müsste ich hier ja praktisch jedesmal ein neues Objekt anlegen?
Wenn ich außerhalb deklariere, dann kennt er wenn ich ReiterA das Objekt zuweisen will kein factoryObject ?
Welche "elegante" bzw. OO-Konforme Lösung würde sich denn hier anbieten um dieser Zwickmühle zu entgehen? 😁
Gruß
Sooo, da ich heute mal wieder Zeit hatte mich damit zu beschäftigen wollte ich den Thread mal wieder aufwärmen 😉
Also ich hab jetzt mal eine kleine Factory angelegt, so wie ich sie früher schon mal in PHP eingesetzt habe.
Factory (Creator):
public abstract class SettingsFactory
{
public abstract Settings FactoryMethod(string type);
}
SettingsObject (Concrete Creator):
public override Settings FactoryMethod(string type)
{
switch (type)
{
case "ReiterA":
return new ReiterASettings();
case "ReiterB
return new ReiterBSettings();
default:
throw new ArgumentException("Falscher Settings Parameter: " + type);
}
}
Settings (Product):
public abstract class Settings
{
abstract public void SaveSettings();
}
ReiterASettings (Concrete Product):
class ReiterASettings : Settings
{
public override void SaveSettings()
{
}
// Hier nun meine eigentliche Frage:
// Kann man das so ähnlich wie hier lösen, das beim Setten des Wertes automatisch ein Event geschossen wird der alle "angehängten" Controls in der Anwendung aktualisiert, wie z.B. ListView
private SEttings myPfadzuDateiX;
public string MyPfadzuDateiX
{
set {
Properties.Settings.Default.PfadzuDateiX = value;
FireEvent();
}
get {
return Properties.Settings.Default.PfadzuDateiX;
}
}
}
INotifyPropertyChanged wäre hier ja hier auch genau richtig oder?
Edit: Naja das mit den Settings und get / set haut ja in der Form garnicht hin oder?
Gruß
Ach du dicke ... 😕
vollkommen richtig Herbivore, ich hab den Fehler wiedermal komplett woanders gesucht. Geclosed waren alle Streams, ... nur NACH dem File.xxx()...
Und dafür über ne Stunde rumgefummelt, manchmal könnt ich mir einfach den Kopp gegen den Tisch knallen... 😁
Hey Leute,
wie der Titel schon sagt, habe ich Zugriffsproblem bei diesen beiden Aktionen.
Folgender Aufbau:
public void DoStuff(...)
{
try
{
lock (this)
{
this.m_StartJobOperation.Post(new SendOrPostCallback(delegate(object state)
{
EventHandler handler = JobStarted;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
// In dieser Methode wird ein File.Move ausgeführt
MoveFile();
}), null);
this.m_StartJobOperation.OperationCompleted();
// Hier werden mehrere Sachen abgehandelt...
this.m_FinishJobOperation.Post(new SendOrPostCallback(delegate(object state)
{
EventHandler handler = JobFinished;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
// Wieder File.Move bzw. File.Delete auf eine im oberen Abschnitt schon benutzte Datei
UndoMoveFile();
}), null);
this.m_FinishJobOperation.OperationCompleted();
}
}
Wie man sehen kann werden bei Start und Beendigung des Threads ein paar Sachen ausgeführt u.a. File Operationen bei denen ich eine "the process cannot access the file because it is being used by another process" Exception bekomme.
Ich kann ja mit File.xxx auch keinen Stream schließen? Hat jemand eine Idee wie ich dieses Problem beheben könnte?
Danke für die Tipps 😃 dann werd ich mich wohl gleich mal ans "umbauen" machen. Der Weg am Anfang ist echt steinig 😉, alle paar Tage darf ich meine Anwendung umbauen, weil ich merke, dass es viel einfachere bzw. "richtigere" 😉 Lösungen gibt.
Eine ganz kleine Frage hätte ich noch, den Vorschlag zwei Forms über eine dritte Klasse kommunizieren zu lassen habe ich aus diesem Thread: Kommunikation zwischen 2 Forms
Hauptzweck dieses Singletons war es, von einem UserControl aus auf die Controls des StatusStrips zuzugreifen, dachte bis jetzt das dies eine saubere Möglichkeit wäre? Nunja inzwischen hab ich ja gelernt das man das auch über Events lösen kann 😃
Ganz genau. Invoke und Controls, die in einem Singleton gehalten werden, klingt sowieso schon recht abenteuerlich...
Das Singleton dient ja egtl. dazu, wenn ich auf ein Control von FormA auf ein Control von FormB zugreifen will, dass müsste ja dann wiederum konform sein schätze ich. Glaube bei dem Invoke hast du mich falsch verstanden, die Singleton Klasse hält nur die Controls, da passiert sonst garnix, Invoke findet schon in der Klasse direkt statt, halt hier z.B. Progressbar im Form aktualisieren.
Durch folgendes Beispiel bin ich auf diesen Ansatz gekommen: Klick
Hier werden ja auch aus der Klasse heraus Controls aktualisiert? Sorry wenn die Frage etwas nervig erscheint, aber mir ist es sehr wichtig, dass ich mir einen sauberen Programmierstil aneigne, da ich noch in den Anfängen stecke.
Hey Leute,
als ich mir diesen Thread durchgelesen habe bin ich ein bisschen ins grüblen gekommen. In einer meiner Klassen, welche Files abarbeitet, greife ich mit Invoke direkt aus einer Methode auf die GUI zu, die Controls auf die ich zugreifen muss sind in einer Singleton Klasse zwischengelagert, damit ich von dort aus zugreifen kann.
Eigentlich verstößt dann mein Ansatz hier gegen die "Sauberkeit" oder und ich sollte statt Invoke in der Methode, nur ein Event feuern welches dann im Form direkt die Controls aktualisiert?
Danke für deine Antwort winSharp 😃 hab viel gegoogelt und habe dann eine Lösung gefunden dir mir persönlich sehr gefällt und zwar mittels des AsynOperationManagers.
protected AsyncOperation m_StartJobOperation;
protected AsyncOperation m_FinishJobOperation;
this.m_StartJobOperation = AsyncOperationManager.CreateOperation(null);
this.m_FinishJobOperation = AsyncOperationManager.CreateOperation(null);
public override void ExecuteBatch(object batchFile)
{
try
{
lock (this)
{
this.m_StartJobOperation.Post(new SendOrPostCallback(delegate(object state)
{
EventHandler handler = JobStarted;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
this.m_Timer.Start();
}), null);
this.m_StartJobOperation.OperationCompleted();
// Cast back to string
string pathToBatch = (string)batchFile;
// Create new process instance
Process p = new Process();
// Set path to batch file
p.StartInfo.FileName = pathToBatch;
// Set current WorkingDir
p.StartInfo.WorkingDirectory = dir;
// Start batch job
p.Start();
// Wait until process is finished
p.WaitForExit();
this.m_FinishJobOperation.Post(new SendOrPostCallback(delegate(object state)
{
EventHandler handler = JobFinished;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
this.m_Timer.Stop();
}), null);
this.m_FinishJobOperation.OperationCompleted();
}
}
Nun kann ich ganz einfach im Form selbst sagen was die Events machen sollen, also in dem Fall Gui vor bzw. nach dem Thread wie gewünscht bearbeiten und einen Timer starten der mir hier sachen in eine ListBox lädt.
Wär interessant zu wissen ob diese Lösung "sauber" ist, da ich das als Anfänger hier noch nicht wirklich einschätzen kann. Ich weis ich das ein BGW dasselbe macht, aber wollte meine bestehende Struktur nicht verändern
Hey SeeQuark,
danke Dir für deine schnelle Antwort 😃
Also Controls während der Abarbeitung zu aktualisieren ist kein Problem, das mit Invoke läuft super und die ProgressBar läuft schön durch. Hab mich etwas schwach ausgedrückt, ich will während der Thread läuft alle anderen Controls disablen und nach Beendigung das ganze wieder invertieren ^^, also die alten StatusStrip controls wieder anzeigen und ProgressBar wieder verschwinden lassen, der Rest läuft schon, einziges Problem ist noch, wie stelle ich fest das der Thread durch ist?
Selbiges Problem habe ich auch noch bei einem fast identischen Fall, selbiges wie hier, nur das in einer for Schleife eine Reihe von nacheinander abgearbeitet wird.
for (int index = 0; index < this.m_ProcessItems; index++)
{
ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ExecuteBatch);
// Start new thread
Thread batchThread = new Thread(pts);
// Start thread and pass path to batch file
batchThread.Start(batchFile[index].getPath);
}
// DoIrgendwas() wenn Thread fertig
Hier werde ich wohl um einen ThreadPool nicht herumkommen oder? (Auch wenn ich mich mit der Thematik noch nicht näher auseinandergesetzt habe)
Gruß
Michi
Hey Leute,
hätte da eine Frage bzgl. Threads. Die folgende Methode wird von einem Thread aufgerufen
ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ExecuteBatch);
Thread batchThread = new Thread(pts);
batchThread.Start(batchFile.getPath);
public new void ExecuteBatch(object batchFile)
{
try
{
lock (this)
{
// Cast back to string
string pathToBatch = (string)batchFile;
Process p = new Process();
// Set path to batch file
p.StartInfo.FileName = pathToBatch;
// Start batch job
p.Start();
// Wait until process is finished
p.WaitForExit();
}
}
Jetzt will ich z.B. unmittelbar vor Start des Threads eine Funktion aufrufen die ProgressBar, StatusLabel usw. im StatusStrip sichtbar macht und wiederum nach Beendigung des Threads verschwinden lässt. Aber wie kann ich denn überprüfen wann der Thread nun beendet ist?
Könnte man die beiden besagten Aktionen auch in Threads stecken und dann mittels Thread.Join das Zeug runterarbeiten oder gibt es anderen Möglichkeiten dies zu erreichen?
Hey Norman-Timo,
entschuldige bitte, da hab ich mich am Anfang des Threads sehr unglücklich bzw. falsch ausgedrückt. Die Theorie der OOP bzw. des OOD ist mir schon bekannt durch einige Vorlesungen, jedoch muss ich es jetzt zum ersten mal in einem etwas größeren Projekt "real" anwenden (Vorher Webentwicklung mit PHP, JS etc...), da tu ich mich noch ein bisschen schwer, aber ich finde mich von Tag zu Tag etwas besser zurecht 😃
Gruß
Michi
Danke für deine Antwort 😃
Da ich wie, schon angesprochen, noch recht neu in der OO Welt bin, hab ich noch nicht ganz verstanden was es mit einer Manager Klasse auf sich hat 😉
Ich versuche mal deine Antwort zu interpretieren soweit es für mich möglich ist.
oder die einzelnen Reitersettings nicht isoliert betrachtest und eine "Manager"-Klasse baust, die den Zugriff auf diese Reitersettings ermöglicht (wiederum mit Interfaces bitte).
Also praktisch die einzelnen Reiter Klassen, als eigenständige Klassen und durch diese Manager Klasse kann ich auf die entsprechend benötigte Settings Klasse zugreifen? Klingt für mich jetzt nach einem Factory Pattern, ich fordere zB eine Instanz von SettingsKlasse ReiterA an und die Manager Klasse spuckt mir diese aus, also verwaltet praktisch alle Anfragen?
Sorry wenn ich jetzt vielleicht komplett am Ball vorbeilaufe, für ein paar Tipps oder weiterführende Links wär ich dir dankbar 😃
Gruß
Danke für deine Antwort norman_timo 😃
Da meine Anwendung in einem TabControl aufgebaut ist, habe ich mir überlegt die SettingsController Klasse zu unterteilen, da es vielleicht sons t zu unübersichtlich wird, weil ich schon eine Menge Settings habe und dazu wohl auch einige Events geschrieben werden müssen, die bei Änderung von Werten entsprechend reagieren.
Nun könnte man doch jeweils eine Klasse für einen Reiter anlegen, welche dann die entsprechenden Events und Settings für jeweiligen verwaltet?
Also Praktisch: Interface -> Oberklasse -> (KlasseReiter1, KlasseReiter2...)
Wäre sowas sinnvoll? Bin noch ziemlich neu in der OOP Welt.
Hey Leute,
derzeit benutze ich in meiner Anwendung zur Speicherung von Settings (insbesondere Pfandangaben), den von .NET zur Verfügung gestellten Settings Provider. Um die Einstellungen vorzunehmen, also Pfade zu speicher etc. verwende ich ein eigenes Form. Bei vielen Änderungen von gewissen Settings, wird sofort nach Änderung des Pfades eine ListView / ListBox aktualisiert. Nun habe ich mir überlegt eine SettingsController Klasse zu erstellen.
Beispiel: Ich ändere Properties.Settings.Default.PfadBlaBla
public int MyPfadBlabla
{
set
{
Properties.Settings.Default.PfadBlabla = value;
AktualisiereControlsEvent();
}
get
{
return Property.Settings.Default.PfadBlaBla
}
}
Macht diese Überlegung Sinn? Ich sehe hier den großen Vorteil, dass ich meine Events zur Aktualisierung der Controls übersichtlich in einer Klasse habe und das ganze zeug schwirrt nicht irgendwo in einer Form rum. Oder soll ich gleich eine eigene Settings Verwaltung schreiben, z.B. Speicherung in einem XML File?
Gruß
Hey Leute,
wollte Euch mal fragen, ob ihr mir ein C# Buch mit relativ vielen und gerne auch umfangreicheren Beispielen empfehlen könnt.
Bis jetzt wurde mir das Visual C# 2008 Kochbuch ans Herz gelegt.
Bin auch Online auf der Suche nach Beispielen, würde mir gerne mal ein umfangreicheres Programm ansehen (am besten mit Design Patterns). Habt ihr noch ein paar gute Tipps, wo es OpenSource Software gibt anhand der man sich mal ein Bild von einem größeren C# Projekt machen kann?
Viele Grüße