Warum sagst du uns denn nicht wie du es gelöst hast? Kennst du das auch, du suchst im Internet nach einer Problemlösung und du findest auch ein paar Ansätze in Foren und zum Schluss steht da nur "habs anders gelöst, danke".
Um das zu vermeiden, würde ich einfach schreiben WIE du es nun gelöst hast.
Hmm bei mir funktionierts unter Linux aber:
cat main.cs
using System;
public class MainC {
public static void Main() {
Console.WriteLine("test");
Console.ReadLine();
}
}
mono --version
Mono JIT compiler version 1.2.3.1, (C) 2002-2006 Novell, Inc and Contributors. [URL]www.mono-project.com[/URL]
TLS: __thread
GC: Included Boehm (with typed GC)
SIGSEGV: normal
Architecture: x86
Disabled: none
Hi Leute,
hab was intressantes rausgefunden. Und zwar, Variante 1 ist schon richtig, allerdings wird das ganze im Excel nur falsch dargestellt. Sobald man zB auf die Zelle A2 klickt, und dann ins fx (wie heißt das?!) klickt, und wieder wegklickt auf eine andere Zelle, dann wird das ganze richtig dargestellt. Also vorher steht zB 0 drinnen, oder 2.6133, nach dieser Prozedur dann eben 0,00 oder 2.61.
Aber das kann doch nicht die Lösung sein? Außerdem noch etwas, bei der Datum-Spalte, wenn nache einem Datum ein Leeres Feld kommt, geht die Formatierung für die nächsten Zellen drauf....
Ist das jetzt ein Excel Bug oder liegt es an mir? Die Lösung für das 1 Problem wäre wahrscheinlich (dummy lösung) alle Zellen zu selektieren und wieder zu deselektieren. Aber das kanns doch auch nicht sein?
Hier die Links zu den Screenshots:
Draufklicken -> http://anarxo.homelinux.org/Variante_1_bla.JPG
Und wieder wegklicke tadaa -> http://anarxo.homelinux.org/Variante_1_bla2.JPG
Hier noch meine Insert Prozedur in das Excel Sheet
// write data
foreach (int merkmalNr in m_Messwerte.Keys) {
cmd.CommandText = "INSERT INTO [Merkmal " + merkmalNr.ToString() + "$] " +
"(Wert, Stichprobenumfang, Anzahl_Fehler, Attribut, " +
"Datum, Ereignisse, Chargennummer, Nestnummer, " +
"Prüfernummer, Maschinennummer, Prozeßparameter, " +
"Prüfmittelnummer) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
foreach (Messwert m in m_Messwerte[merkmalNr]) {
//fill parameters
cmd.Parameters.Add("Wert", OleDbType.Double).Value = m.Wert;
cmd.Parameters.Add("Stichprobenumfang", OleDbType.Integer).Value = m.Stichprobenumfang;
cmd.Parameters.Add("Anzahl_Fehler", OleDbType.Integer).Value = m.AnzahlFehler;
cmd.Parameters.Add("Attribut", OleDbType.SmallInt).Value = m.Attribut;
if (m.Datum_Zeit != null) {
cmd.Parameters.Add("Datum", OleDbType.Date).Value = m.Datum_Zeit;
} else {
cmd.Parameters.Add("Datum", OleDbType.Date).Value = DBNull.Value;
}
cmd.Parameters.Add("Ereignisse", OleDbType.Integer).Value = m.Ereignisse;
cmd.Parameters.Add("Chargennummer", OleDbType.VarChar).Value = Convert.ToString(m.Chargennummer) + "";
cmd.Parameters.Add("Nestnummer", OleDbType.VarChar).Value = Convert.ToString(m.Nestnummer) + "";
cmd.Parameters.Add("Prüfernummer", OleDbType.VarChar).Value = Convert.ToString(m.Prüfernummer) + "";
cmd.Parameters.Add("Maschinennummer", OleDbType.VarChar).Value = Convert.ToString(m.Maschinennummer) + "";
cmd.Parameters.Add("Prozeßparameter", OleDbType.VarChar).Value = Convert.ToString(m.Prozeßparameter) + "";
cmd.Parameters.Add("Prüfmittelnummer", OleDbType.VarChar).Value = Convert.ToString(m.Prüfmittelnummer) + "";
//execute query
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
Vielleicht weiß ja jemand hier wo das Problem liegt...
lg
Bakunin
Hi Leute,
genau der Thread den ich suchte 🙂. Allerdings komme ich einfach nicht dahinter, wieso meine Spalten nicht formatiert werden.
Ich erstelle ein Excel file, nach Rainbirds Beispiel [1], danke an dieser Stelle an Rainbird 🙂. Das ganze klappt wunderbar. Nur jetzt sollte ich eben die Spalten noch formatieren. Da ergab sich bei mir die erste Frage, wie selektiere ich eine ganze Spalte?
Irgendwo habe ich dann das im Forum gefunden:
Excel.Range oRange = (Excel.Range)ws.Columns[SpaltenNummer, Type.Missing];
Da ich das ganze per Reflection mache, sieht dazu mein Code so aus:
range = sheet.GetType().InvokeMember("Columns", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { i, Type.Missing });
So, um nun die Spalte zu formatieren verwende ich folgendes:
range.GetType().InvokeMember("NumberFormat", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, range, format);
In format steht zB "0,00", "0", "TT.MM.JJJJ HH:mm:ss".
Tja das wars, leider funktioniert es nur nicht...
Ich hab dann mal was anderes versucht:
range = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { 2, i });
object entirecolumn = range.GetType().InvokeMember("EntireColumn", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, range, new object[0]);
entirecolumn.GetType().InvokeMember("NumberFormat", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, entirecolumn, format);
Und siehe da, es wird was formatiert. Die Dezimalzahlen werden mit 2 Kommastellen angezeigt, die Zahlen überhaupt als Zahl gespeichert und nicht als Text. Nur ein Manko gibt es noch, und zwar das Datum. Das Datum wird in der ersten Zeile richtig formatiert, in den nächsten Zeilen wird die Zeit abgeschnitten, es wird einfach als Datum formatiert, aber nicht in dem Stil wie ich will ("TT.MM.JJJJ HH:mm:ss").
Jetzt stellt sich die Frage, warum funktioniert das überhaupt, wenn ich anstatt
range = sheet.GetType().InvokeMember("Columns", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { i, Type.Missing });
das hier mache:
range = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { 2, i });
Das ergibt für mich gar keinen Sinn. Wenn ich mir die Formatierung von Zellen anschaue die leer sind - stimmt sie auch nicht mit der Formatierung die ich bestimmt habe überein, sondern es ist einfach das "Standard" format.
Anbei noch zwei Screenshots zur Variante 1 [2] und 2 [3]. Außerdem hier nochmals der ganze Code:
foreach (DataColumn column in table.Columns) {
i++;
// Insert fieldname
object range = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { 1, i });
range.GetType().InvokeMember("Value", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, range, new object[1] { column.ColumnName });
object[] format = null;
if(column.DataType.Equals(typeof(double))){
string s = "0" +
System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
for (int digits = 0; digits < System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalDigits; digits++) {
s += "0";
}
format = new object[] { s.ToString() };
}else if(column.DataType.Equals(typeof(int))){
format = new object[] { "0" };
}else if(column.DataType.Equals(typeof(Int16))){
format = new object[] { "0" };
}else if(column.DataType.Equals(typeof(DateTime))){
format = new object[] { "TT.MM.JJJJ HH:mm:ss" };
}else if(column.DataType.Equals(typeof(string))){
format = new object[] { "" };
}
//Excel.Range oRange = (Excel.Range)ws.Columns[SpaltenNummer, Type.Missing];
range = sheet.GetType().InvokeMember("Columns", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { i, Type.Missing });
//range = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { 2, i });
//range.GetType().InvokeMember("EntireColumn", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, range, new object[0]).GetType().InvokeMember("NumberFormat", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, range, format);
range.GetType().InvokeMember("NumberFormat", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, range, format);
}
lg
Bakunin
[1] http://www.mycsharp.de/wbb2/attachment.php?attachmentid=1541
[2] http://anarxo.homelinux.org/Variante_1.JPG
[3] http://anarxo.homelinux.org/Variante_2.JPG
Hallo Cord Worthmann,
danke für die Antwort. Ich habe eine CodeBehind Datei erstellt, alles funktioniert soweit auch wunderbar. Allerdings kann ich aus der CodeBehind Datei auch nicht auf das "user" Objekt zugreifen.
Kannst du mir vl genauer erklären was du meinst?
Hier die Global.asax
<%@Application Language="C#" Inherits="Global" %>
<%@Assembly name="core" %>
<object id="user"
runat="server"
scope="session"
class="Test.User.User"
/>
Die zugehörigen Global.asax.cs:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e) {
// Code that runs on application startup
}
void Application_End(object sender, EventArgs e) {
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e) {
// Code that runs when an unhandled error occurs
//todo log4net
}
void Session_Start(object sender, EventArgs e) {
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e) {
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
}
Also wie gesagt ich würde gerne ganz einfach auf das "user" Objekt - welches in der Global.asax definiert ist - hier auch zugreifen können (und auch in allen anderen CodeBehind files).
also zB in der Login.aspx.cs:
protected void Login_Authenticate(object sender, AuthenticateEventArgs e) {
try {
Test.User.User newUser = Test.User.User.Login(Login.UserName, Login.Password);
//hier will ich jetzt auf das Session Scope Objekt "user" zugreifen
user = newUser;
Response.Redirect(@"./Index.aspx");
} catch (Test.User.Exceptions.LoginFailedException LoginFailedException) {
}
}
lg
Bakunin
Hallo Leute,
ich habe mir gerade dieses Tuto angeschaut:
http://www.galileocomputing.de/openbook/asp/asp110002.htm#Rxxasp11607InstanzeneigenerKlassenindenSitzungsdatenspeichern
Es geht darum, ein Objekt global Zugreifbar zu machen (auf allen ASP.NET Seiten).
So hier mal meine global.asax:
<%@ Application Language="C#" %>
<object id="user"
runat="server"
scope="session"
class="Test.User.User"
/>
So, jetzt will ich von einer aspx Seite darauf zugreifen. Funktioniert wunderbar.
Aber wenn ich aus der Code Behind Klasse darauf zugreifen will, scheint das Objekt nicht in der Intellisense auf - und der Zugriff funktioniert auch nicht.
Muss mensch etwas bestimmtes beachten wenn mensch solche Scope Objekte in Code Behind Klassen verwenden will?
Hab leider nichts gefunden.
lg
Bakunin
Danke an euch beide, werde mir heute das ganze genauer ansehen. Werd mal die MSDN zu den genannten Methoden mal durchstöbern.
lg
Bakunin
Hallo Ifoko,
gibt es einen Designer für die Webcontrolentwicklung? Also ich möchte im Control selber <div> Controls verwenden.
Also nochmal, falls ich mich unklar ausgedrückt habe. Ich möchte ein Webcontrol entwickeln. In diesem Webcontrol werden 3 Textboxen und 3 Labels verwendet. In der CreateChildControls Methode mache ich es bis jetzt so, dass ich ein Tabel Control erstelle. Diese Table hat 2 Spalten, links liegt immer ein Label, rechts eine Textbox. Da ich meine aber, dass Table nicht für das Layout verwendet werden soll, würde ich es eben gerne anders lösen.
Und darum hätte ich gerne ein paar Links mit Anleitung zur Webcontrolentwicklung. Also was ist der beste Weg etc. Die Sites die ich bis jetzt gefunden habe, verwenden auch alle Tables um die ChildControls in ihrem eigenen Control wie gewünscht anzuordnen.
Bleibt die Frage, ob das so ok ist, oder eben nicht? (Wie gesagt Table sollte doch normalerweise nicht fürs "layouten" verwendet werden?)
lg
Bakunin
Also ich hab mal weiter gesucht im Netz aber ich finde nichts brauchbares. Komisch eigntlich, hab gedacht zum Thema Webcontrol developing gibt es gute HowTos... naja bei denen Sites die etwas mit dem Thema zu tun hatten bin ich immer wieder auf Tables gestoßen.
Gibt es wirklich keine andere Möglichkeit die ChildControls im Control selber anzuordnen?
lg
Bakunin
Hallo Leute, ich hab bis jetzt nichts zu diesem Thema im Forum gefunden, bzw nicht das richtige.
Mein Problem besteht darin, dass ich ein eigenes Webcontrol entwickeln will, dass es ermöglicht einen Text mit Zusammenfassung und Titel zu speichern (also 3 Textboxen).
Jetzt möchte ich das die Labels (Beschreibung der Textboxen [Titel, Zusammenfassung, etc]) und die Textboxen in einer tabellarischen Form angezeigt werden.
Also:
Titel:..........................[Textbox]
Zusammenfassung:.....[Textbox]
Inhalt:........................[Textbox]
Ich könnte jetzt die Render Methode überschreiben und alles in eine Tabelle packen (Table Control). Aber ich würde das gerne mit DIVs lösen - die Diskussion warum DIVs anstatt Table möchte ich hier aber nicht aufleben lassen 🙂 - weiß aber nicht wirklich wie ich das machen soll. Gibt es generell eine gute Anleitung für die Webcontrolentwicklung? Gerade bezogen auf den Aufbau des Controls.
Zur Zeit weiß ich nicht wirklich wie ich das "schön" lösen könnte. Für ein paar gute Links wäre ich dankbar - aber natürlich auch für ein paar Vorschläge 🙂.
Vielen Dank im Voraus
lg
Bakunin
PS: Wenn es möglich ist, möchte ich nicht umbedingt einen HTML Code in die Render Methode übernehmen (Außer das wäre Standard).
Original von sh4rk
treeview...mfg hannes
Ich weiß nicht ob du mich falsch verstanden hast - ich will die Klassenansicht im Visual Studio 2005 umstellen. Dass eine hierarchische Struktur der Namespaces entsteht.
Falls du mich richtig verstanden hast, bitte ich um mehr Infos.
Hallo Leute,
ist es möglich in VS 2005 die Class View so einzustellen, dass die Namespaces in hierarchischer Reihenfolge angezeigt werden?
Also im Moment siehts so aus:
ich hätte aber lieber:
Ist das irgendwie möglich? bin schon am verzweifeln X(
lg
Bakunin
Hi Vinx,
du könntest auch löschweitergabe bei den tabellen integrieren. per foreign keys.
lg
Bakunin
Hallo svenson,
Original von svenson
Nur passiert einem die Manipulation einer Variablen via Reflection mal nicht "aus Versehen". Das sind ein paar Zeilen Code.
Ich habe eigentlich gemeint, dass der "Benutzer" meines Codes, mal auf die schnelle eine private Methode aufruft, oder eine private Variable setzt, weil er zB zu faul ist um sich die Doku o.ä. anzusehen um zu verstehen, warum man keinen direkten Zugriff auf diese Methoden und Variablen hat.
Aber du hast schon recht, Mißbrauchquelle ist der richtige Begriff.
lg
Bakunin
Original von herbivore
Hallo Bakunin,Schade, ich hatte ja nun wirklich handfeste Beispiel genannte. Es wundert mich auch wirklich, dass die dich nicht überzeugen. Wie gesagt, sinnvoll ist es im Wesentlichen nur für Service-/Infrastruktur-Klassen, aber da ist es auch sinnvoll.
So wie man in C++ die Pointer-Arithmetik zum unsinnigen Zugriff missbrauchen kann, kann man in C# die Reflection dazu missbrauchen. Aber jede Technik lässt sich missbrauchen. Wenn man den Wert einer Technik nur nach den Missbrauchsmöglichkeiten bewertet, ist man m.E. auf dem Holzweg. Und der Nutzen von Reflection ist auf jeden Fall gegeben.
herbivore
Hallo herbivore,
ich konnte die Beispiele gestern nicht mehr durchlesen. Habe ich aber jetzt gerade gemacht.
zum 1 Beispiel: Hast du das eigentlich noch irgendwie gelöst? Würde mich interessieren.
zum 2 Beispiel: Sehr interessante Geschichte! Und das Beispiel hat mich eigentlich auch überzeugt, dass es sinnvoll sein kann 🙂.
Klar kann man jede Technik missbrauchen, aber wie gesagt: je weniger sich missbrauchen lässt, desto weniger wird missbraucht (also davon bin ich überzeugt ^^).
Aber das 2 Beispiel hat mich wie gesagt überzeugt und für solche Fälle ist es auf jeden Fall ok! Solange man Reflection bewusst einsetzt ist es wirklich toll!
Danke nochmals für die Antworten herbivore.
Original von herbivore
Hallo Bakunin,Somit kannst du dich als Entwickler ja nichtmal mehr darauf verlassen (oder gibt es eine Möglichkeit?), dass jemand deine Privaten Felder manipuliert
wenn du eine Klasse schreibst, die nicht funktioniert, weil der Benutzer der Klasse unsinnig auf die privaten Felder zugreift, ist das nicht dein Problem.
Stimmt auch wieder 🙂
Original von herbivore
Ist das eigentlich nur bei .NET so oder auch in anderen Sprachen?
In C++ ist es noch viel leichter auf die privaten Felder zuzugreifen. Da C++ mit Headerfiles arbeitet, brauchst du dort nur private in public zu ändern und schon hast du vollen Zugriff.
Das ist meiner Meinung nach was anderes, denn hier veränderst du den Code!
Die ersten zwei Links hatte ich eh schon gefunden. Ich werde mir das noch genauer anschaun.
Vielleicht werde ich selbst mal feststellen, dass es sinnvoll ist, aber z.Z kann ich es mir nicht vorstellen. Klar, wenn ich wie du mal denken würde, dass zB eine Methode public sein sollte, dann ist sowas fein... aber ehrlich gesagt ändere ich dann lieber den Code... wobei der Code dann natürlich opensource sein muss 🙂. (Was sowieso so sein sollte 😉).
Danke für die Antworten!
lg
Bakunin
//edit
jetzt ist mir noch was eingefallen 😉
und zwar.. Wenn du sagst, der User ist dann selbst Schuld ist meiner Meinung schon auch richtig. Aber wenn der User nichtmal die Möglichkeit dazu hätte, könnte er auch nichts anrichten 🙂.
Wenn ein Entwickler in VB6 ein Boolean Datentyp in einen String umwandelt (vielleicht sogar durch einen Fehler) und VB6 lässt das zu, dann ist natürlich auch der Entwickler Schuld, aber es wäre aus meiner Sicht auch besser wenn VB6 sowas gar nicht zulassen würde!
Oder hast du (ihr) da andere Ansichten?
lg
Bakunin
Original von herbivore
Hallo Bakunin,es gibt diverse Fälle, in denen der Zugriff auf private Felder anderer Klassen notwendig und sinnvoll ist, z.B. in BinaryFormatter um beliebige Objekte serialisieren zu können. Ich habe der Zugriff auf private Felder anderer Klassen auch schon in eigenen Service-Klassen benutzt. In Business-Klassen hat sowas aber nichts zu suchen.
herbivore
Was mich ein wenig stört ist, dass meiner Meinung nach sowas einfach nicht passieren darf. Somit kannst du dich als Entwickler ja nichtmal mehr darauf verlassen (oder gibt es eine Möglichkeit?), dass jemand deine Privaten Felder manipuliert ... ich denke da erschließt sich dann eine große Fehlerquelle.
Ist das eigentlich nur bei .NET so oder auch in anderen Sprachen?
PS: Erklär doch bitte genauer wieso du einen Zugrif auf die Privaten Felder gemacht hast, dann könnte ich mir vielleicht besser vorstellen warum sowas möglich sein soll.
Danke,
Bakunin
Hallo Community,
ich habe schon im Forum gesucht, aber leider nichts zu diesem Thema gefunden. Und zwar... warum ist es möglich per Reflection auf Private Felder zuzugreifen und diese sogar zu verändern?
Private Felder sind doch dazu da, damit außenstehende dass genau nicht machen können!
zB erstelle ich Propertys damit nicht direkt auf ein Feld zugegriffen wird, um vielleicht eine Prüfung o.ä. durchzuführen. Aber per Reflection kann man jetzt direkt auf das Feld zugreifen und den Wert ändern...
Kann mir irgendjemand von euch erklären was da der Sinn dahinter ist?
Gruß
Bakunin
Original von flummox
...Persoenlich kann ich mir allerdings nichts besseres als MonoDevelop vorstellen. Mittlerweile sehr stabil, mit allen Vorteilen von SharpDevelop und der Geschwindigkeit von VC#, Herz was willst du mehr. 🙂
...
Ich bevorzuge auch MonoDevelop, vorallem weil ich am liebsten in der Linux Umgebung arbeite.
Arbeitest du auch mit dem MonoDebugger? (Hab ihn noch nicht wirklich zum laufen gebracht, und MonoDevelop hat ihn sowieso vorerst mal rausgenommen).
Ich komme irgendwie recht gut ohne Debugger aus, was mich eigentlich wundert 🙂. Wobei ich gemerkt habe, dass ich ohne Debugger mehr aufpasse beim coden.
Dazu müsstest du den Enum so umschreiben:
enum test: uint {
Hallo = 0;
Bis bald = 1;
}
enum test1: uint {
Hi = 0;
Tschüss = 1;
}
Und dann halt
b = (uint) a;
Also kennt keineR dass Problem...
naja dann wäre die Frage halt, wie kann ich 2 Texte miteinander vergleichen die ein unterschiedliches Format haben:
Also dass Prüfbeginn == Prüfbeginn -> true ergibt...
Bakunin
Hi Leute.
Ich finde nichts brauchbares im Netz, vielleicht hat jemand von euch Erfahrungen damit. Ich verwende den MySQL Connector 1.0.6. Klappt wunderbar. Nur eine Sache nervt:
SHOW FIELDS FROM [Tabelle];
Ich kann den Befehl ausführen, es passt eigentlich alles. Nur eines nicht, wenn in einem Spaltennamen ein ü, ä oder ö vorkommt, sowie ein ß und halt andere Sonderzeichen. Dann gibt es mir diese Zeichen eben nicht also solche zurück.
Bsp: Prüfbeginn anstatt Prüfbeginn.
Mit MySQL5 funktioniert es aber!
Hier noch ein kleiner Code:
strSQL = "SHOW FIELDS FROM " + strTable + ";";
oReader = this.DBHandle.execReader(strSQL);
//Spaltennamen auslesen.
oField.StandardisationName = oReader.GetString(0);
//String vergleich (nur ein Bsp)!
if(oField.StandardisationName == "Prüfbeginn")
{
Console.WriteLine("juhu");
}
So, nun könnte ich natürlich eine Funktion schreiben dir mir die ganzen Sonderzeichen richtig darstellt. Aber da gibts sicher bessere Lösungen.. hoffentlich. Vielleicht gibt es ja eine Funktion die zwei Strings vergleicht die ein unterschiedliches Encoding haben. Also zB "ü" für ein "ü".
Danke im Voraus
Bakunin
Danke für die Antwort.
Ich habs jetzt so gelöst, dass der ganze SQL geparsed wird, und die Parameter die ein VALUE von DBNull haben, werden durch IS NULL erstetzt.
Ist zwar nicht wirklich eine schöne Lösung.. aber naja. Ich denke es wäre durchaus von Vorteil wenn das aber anders lösbar wäre, also über die Parameter.
Bakunin
Hi Leute,
ich habe schon im Forum gesucht, aber nichts passendes gefunden. Falls ich was übersehen habe, sry.
Also mein Problem: Ich möchte ein Select auf eine Tabelle machen. Ich mache das ganze mit Parameter.
MySql.Data.MySqlClient.MySqlConnection conn = new MySqlConnection("server=localhost;user id=root;password=;database=a");
conn.Open();
MySql.Data.MySqlClient.MySqlCommand x = new MySqlCommand();
x.Connection = conn;
x.CommandText = "SELECT RevisionsNr FROM asdf WHERE b = ?b";
x.Parameters.Add("b", MySql.Data.MySqlClient.MySqlDbType.VarChar);
x.Parameters["b"].Value = DBNull.Value;
object o = x.ExecuteScalar();
Console.WriteLine(o);
conn.Close();
So, wie man sieht möchte ich einen Datensatz auslesen der ein DBNull beinhaltet. Nur geht das so nicht? Bzw ich bekomme als Rückgabewert NULL. Der Rückgabewert sollte aber 3 sein. Der Syntax für eine NULL Abfrage im SQL wäre ja "IS NULL".
Muss man jetzt wirklich jedesmal überprüfen ob das Value von einem Parameter DBNull ist, und dann das Select Statement abändern?
Eventuell wäre es von Vorteil hiermal ein paar gute Tutorials zu diesem Thema zu posten. Ich selber kenne jetzt keines das genau auf dieses Problem eingeht.
Schönen Abend noch
Bakunin
Hi herbivore,
Dann ist ja alles gut 😉. Aber damit du weißt was sich konkret geändert hat:
Der Inhalt der Funktion onLoadMainConfig aus dem Controller, wurde direkt in das "View" übernommen. In diese Funktion onDruidPageMainConfigPrepare.
Bakunin
So, jetzt die richtige Antwort.
Also würdest du das so machen: (onDruidPageMainConfigPrepare Funktion)
//VIEW
//============================DELEGATES===========================
//public delegate void closeWindow();
//public delegate void loadMainConfig();
//============================DELEGATE EVENTS=====================
//public event closeWindow onClose;
//public event loadMainConfig onLoadMainConfig;
public ConfigurationView (){
}
public void show(){
Application.Init ();
Glade.XML gxml = new Glade.XML (null, "gui.glade", "frm_Configuration", null);
gxml.Autoconnect (this);
//(.....)
Application.Run ();
}
public void close(){
Application.Quit();
//if(this.onClose != null) this.onClose();
}
public void showErrorMessage(string Message){
//(...)
}
public bool showQuestionDialog(string Message){
//(...)
}
public string showFileChooser(string Message){
//(...)
}
//============================GLADE EVENTS===================================
private void onFrmConfigurationDeleteEvent (object sender, DeleteEventArgs a){
this.close();
a.RetVal = true;
}
private void onDruidPageMainConfigPrepare(object sender, EventArgs e){
//if(this.onLoadMainConfig != null) this.onLoadMainConfig();
//-----------ÄNDERUNG-------------- (m_MainConfig Variable existiert noch nicht, ist jetzt nur mal zur Veranschaulichung)
//Show the main config
this.Server = this.m_MainConfig.DatabaseServer;
this.User = this.m_MainConfig.DatabaseUser;
this.Password = this.m_MainConfig.DatabasePassword;
this.Database = this.m_MainConfig.DatabaseName;
this.TagFile = this.m_MainConfig.TagConfigFilePath;
this.LogFile = this.m_MainConfig.LogFilePath;
}
Somit befindet sich der Code, der vorher im Controller abgearbeitet wurde nun im Layoutcode (also nicht View, da ja View und Controller hier vereint sind... wenn ich dich richtig verstanden habe).
Bakunin.
Hi herbivore,
ich habe kein Problem wenn jemand Kritik übt, also musst du dich nicht entschuldigen. Ich wollte ja wissen was daran gut oder schlecht ist, oder ob es gänzlich "falsch" ist.
Ich kann im Moment gerade schlecht mehr schreiben, ich werde später noch ein paar Fragen zu deinem Post stellen.
Bis später
Bakunin
Hallo herbivore,
ich beschäftige mich damit wie gesagt erst seit kurzem. Ich habe es eigentlich so gemacht, damit eine komplette Trennung zwischen View und Model entsteht. Also das View kennt nicht das Model und das Model kennt nicht das View. Der Controller ist also die Schnittstelle zwischen den beiden. Wenn sich jetzt etwas im Model ändert, muss der Controller angepasst werden, aber nicht das View. Das View greift immer noch auf die gleiche Schnittstelle im Controller zu.
@Rainbird
Danke für die Erklärung.
Ob es so eben Vorteile hat und Nachteile hat wollte ich ja fragen. Ich habe es wie gesagt so strukturiert um eine komplette Trennung der Logik mit dem Layout zu erreichen.
Also hier ein kleines Bsp wie es so funktioniert:
//VIEW
//============================DELEGATES===========================
public delegate void closeWindow();
public delegate void loadMainConfig();
//============================DELEGATE EVENTS=====================
public event closeWindow onClose;
public event loadMainConfig onLoadMainConfig;
public ConfigurationView (){
}
public void show(){
Application.Init ();
Glade.XML gxml = new Glade.XML (null, "gui.glade", "frm_Configuration", null);
gxml.Autoconnect (this);
//(.....)
Application.Run ();
}
public void close(){
Application.Quit();
if(this.onClose != null) this.onClose();
}
public void showErrorMessage(string Message){
//(...)
}
public bool showQuestionDialog(string Message){
//(...)
}
public string showFileChooser(string Message){
//(...)
}
//============================GLADE EVENTS===================================
private void onFrmConfigurationDeleteEvent (object sender, DeleteEventArgs a){
this.close();
a.RetVal = true;
}
private void onDruidPageMainConfigPrepare(object sender, EventArgs e){
if(this.onLoadMainConfig != null) this.onLoadMainConfig();
}
//Controller
private ConfigurationController(){
}
public static ConfigurationController getConfigurationController(string MainConfigFile){
ConfigurationController oCC = new ConfigurationController();
oCC.m_MainConfigFile = MainConfigFile;
oCC.m_ConfigView = new ConfigurationView();
oCC.m_ConfigView.onClose += new WikiDoc.IO.GUI.Views.ConfigurationView.closeWindow(oCC.onClose);
oCC.m_ConfigView.onLoadMainConfig += new WikiDoc.IO.GUI.Views.ConfigurationView.loadMainConfig(oCC.onLoadMainConfig);
return oCC;
}
public void show(){
this.m_ConfigView.show();
}
public void close(){
if(this.onCloseView != null) this.onCloseView();
}
//============================EVENTS===================================
private void onClose(){
this.close();
}
private void onLoadMainConfig(){
//(....)
//Show the main config
this.m_ConfigView.Server = this.m_MainConfig.DatabaseServer;
this.m_ConfigView.User = this.m_MainConfig.DatabaseUser;
this.m_ConfigView.Password = this.m_MainConfig.DatabasePassword;
this.m_ConfigView.Database = this.m_MainConfig.DatabaseName;
this.m_ConfigView.TagFile = this.m_MainConfig.TagConfigFilePath;
this.m_ConfigView.LogFile = this.m_MainConfig.LogFilePath;
}
}
Der Code ist natürlich stark gekürzt (Fehler einfach übersehen). Hoffentlich es ist jetzt ein wenig klarer. Achja damit keine all zu große Verwirrung entsteht, dass ganze ist unter mono geschrieben und es ist eine Glade# Anwendung.+
Ok, und der "bessere" Ansatz wäre also (außer es tritt der Fall ein wie Rainbird erklärt hat), wenn das View auch direkt auf das Model zugreifen kann? Aber ist es dann immer noch eine strikte Trennung zwischen Layout und Logik? Also wenn die View Komponente direkt auf das Model zugreifen kann? Und was für eine Rolle spielt dann überhaupt der Controller?
Hier wäre ich auch um ein Code Bsp. erfreut 🙂. Außer ich habe zuviele Links übersehen.
Bakunin
Hi,
ich finde diesen Thread sehr interessant und ich habe mich in letzter Zeit auch ein wenig mit MVC beschäftigt. Mir ist es wichtig dass der grafische Code komplett vom logischem Code getrennt ist. Deswegen lasse ich kein View auf ein Model direkt zugreifen.. aber im MVC Pattern ist das ja so festgelegt oder? Ich kann aber nicht wirklich verstehen wieso.
Also meine Vorgehensweise:
View<-----Controller------>Model
Die View kommuniziert mit dem Controller übrigens auch nur über Events. Der Controller ist immer an ein View angepasst. Und der Controller hat zugriff auf das Model. Aber wie gesagt, das View greift nie direkt auf das Model zu.
Beispiele:
* Der Controller ruft eine Funktion aus dem Model auf. Diese Funktion schlägt fehl. Der Controller ruft eine Funktion aus der View auf, die eine MessageBox zeigt mit dem Fehler.
* Das View fügt einen neuen Kunden in einen TreeView hinzu. Das View führt nun einen Event aus, der Controller fängt dieses Event ab und fügt den Kunden in das Model hinzu.
So, was haltet ihr davon? Gibt es dabei gravierende Nachteile?
Danke herbivore, sehr schön 🙂
Ich habe angefangen TDD umzusetzen und es gefällt mir wirklich sehr gut. Wobei ich aber immer zuerst ein UML erstelle, also ein Klassendiagramm. Dann diese Struktur aufbaue, also die Methoden etc aber ohne implementierung. Dann erst schreibe ich die Tests.... somit baue ich die Struktur zwar nicht durch das Testen auf, aber dass hat mich sowieso nicht wirklich überzeugt. Denn ich finde die Struktur sollte schon zuerst auf einem Blatt Papier entstehen.
Falls ich jetzt komplett daneben liege, dann sagts ruhig 🙂.
BTW: ich glaube jetzt kann man es gar nicht mehr Testgetriebene Entwicklung nennen, denn ich überprüfe die Methoden ja eigentlich nur. Also eher Unit Testing. Aber wenn ich zB eine neue Anforderung habe für eine Klasse, dann schreibe ich immer zuerst einen Test und dann wird implementiert. Aber wie gesagt, am Anfang baue ich die Struktur eigentlich ohne Tests.
Bakunin
Ah ok, daran habe ich gar nicht gedacht. Vielen Dank
Und danke für den Tipp Programmierhans!
Bakunin
Also ich hoffe ich habe dich richtig verstanden.
Hier mein aktualisierter Code:
public void writeConfiguration(string Path, object Configuration){
try{
using(TextWriter oWriter = new StreamWriter(Path)){
XmlSerializer oSerial = new XmlSerializer(Configuration.GetType());
oSerial.Serialize(oWriter, Configuration);
}
}
catch(System.Exception e){
throw e;
}
}
//Aufruf
try{
this.oCHandler.writeConfiguration("/tmp/myconfig.xml", oConfig);
}
catch(System.Exception e){
//Errorhandling
}
Also lieber Exceptions werfen...
na dann, tu ich sowieso lieber 😉
/edit
Und als Rückgabetyp in dem Fall void? Weil wenn eine Exception geworfen wird, dann verabschiedet man sich aus der Funktion oder?
Vielen Dank
Hi Leute,
ich habe ein grundlegendes Designproblem. Und zwar arbeite ich sehr gerne mit Try und Catch, da es so sehr leicht ist Fehler abzufangen. Aber Try und Catch ist meiner Meinung nach sehr sehr langsam. Darum sollte man (denke ich) alle Fehler die man ohne Try und Catch abfangen kann, vorher schon abfangen und als Rückgabewert einer Funktion bool wählen und True oder False zurückgeben, anstatt eine Exception zu werfen.
Dabei ergibt sich aber dass Designproblem (vl ist es ja gar kein Problem und so genau richtig), dass man nun in jeder Klasse einen string braucht indem die Errormessage steht.
zB:
public class ConfigurationHandler{
private string m_Error;
public string Error{
get{ return this.m_Error; }
}
public bool writeConfiguration(string Path, object Configuration){
try{
using(TextWriter oWriter = new StreamWriter(Path)){
XmlSerializer oSerial = new XmlSerializer(Configuration.GetType());
oSerial.Serialize(oWriter, Configuration);
return true;
}
}
catch(System.Exception e){
this.m_Error = e.Message;
return false;
}
}
}
//Aufruf
XMLConfiguration.ConfigurationHandler x = new XMLConfiguration.ConfigurationHandler();
if(!x.writeConfiguration("fail", null)){
Console.WriteLine(x.Error);
}
So, was mich wie gesagt stört, ist dass in jeder Klasse nun ein Error string vorhanden sein muss, worin der Exception-Fehler gespeichert wird.
Da gibt es doch sicherlich bessere Designansätze....
lg
Bakunin
MonoDevelop was originally a port of the SharpDevelop IDE (
> ) to Gtk#, but it has evolved a lot since the initial port.
Hm bestimtme Features von MonoDevelop die die Portierung rechtfertigen....
Ich poste einfach mal die Homepage 🙂http://www.monodevelop.com
Ich komme mit MonoDevelop super zurecht, und ich habe bis jetzt noch nichts vermisst was ich im VS hatte.. aber ich habe mit dem VS auch nicht soviel gearbeitet. Aber VS hat sicherlich viel mehr Features, aber ich brauche diese halt nicht. Und obwohl MonoDevelop sicherlich vieles nicht hat, hat es eines, nämlich die GPL 🙂.
Bakunin
Von der Monodevelop HP:
Does MonoDevelop work on Windows?
No. There was an attempt to make the port some time ago, but work on this is currently stopped. The biggest thing is trying to get the dependencies, such as, gtkhtml, gtksourceview, VFS, and GNOME dependencies working on Win32.
Ich arbeite hauptsächlich mit Monodevelop unter Linux, dass geht sehr gut. SharpDevelop hatte ich mir mal kurz angeschaut, hat mich aber eher abgeschreckt (bei mir was es damals extrem langsam).
Ein Monodev für Windows wär echt Klasse, aber vielleicht sollte man sich da einfach an SharpDevelop wenden und dieses Projekt dementsprechend abändern? Naja nur ein Vorschlag. Ich arbeite eh nicht unter Windows 😜
Danke für die Antworten,
mein Problem liegt darin, dass ich bis jetzt überhaupt nicht so entwickelt habe. Dass ist eine große Umstellung glaube ich. Ich habe mir das Buch "Patterns Konkret" gekauft, und für mich ist das Buch schon schwer zu lesen. Dass einzige was ich jetzt halbwegs verstanden habe, ist eben XP und Unit Testing.
Ziel ist es, so einfachen und primitiven Code wie möglich zu schreiben, der gerade das erledigt, was er soll. Vorkehrungen für etwaiige, zukünftige Anforderungen werden rigoros ausser Acht gelassen. Man kennt sie ohnehin nicht. Ansonsten steckt man viel Aufwand in etwas was später in der Form niemals erforderlich sein wird. Da man aber den Quatsch nicht wieder entfernen möchte, war ja viel Arbeit, versucht man alle notwendigen Änderungen ins geschaffene "Framework" zu integrieren. So steigt der Aufwand für Änderungen langsam ins Unermessliche.
So wie du Beschrieben hast, wie man Programmieren soll Pulpapex, so mache ich dass auch eigentlich (oder ich nehme es an g).
Was sich aber auch durch das Testgetriebene Entwickeln
ergibt, ist das Zusammenspiel der Klassen, wer hat eine
Assoziation bzw. Aggregation mit welcher Klasse.
Das ist interessant, denn ich versuche diese Verknüpfungen bereits vor der Programmierung zu lösen. D.h. auf einem Blatt Papier, dann UML.
Kunde meldet bei folgenden Schritten
passiert das und das ... dann stelle ich dieses Scenario
als Test nach und kann somit schnell Fehler finden.
Das wäre mir gar nicht in den Sinn gekommen. Aber stimmt, so ist es viel leichter einen Fehler zu finden.
Danke für die Antworten. Ich finde das Thema sehr interessant und deswegen werde ich mir gleich noch mehr zu dem Thema reinziehen 🙂.
Bakunin
try{
string qry = "DELETE FROM wp_users WHERE ID='"+ID+"'";
MySqlCommand teil2 = new MySqlCommand(qry, oMySqlConn);
teil2.Prepare();
//SQL ausführen
teil2.ExecuteNonQuery(); //Jetzt wird das SQL Statement ausgeführt. Wenn dabei ein Fehler auftritt wird das ganze beim catch Teil ausgegeben.
catch(System.Exception e){ //du kannst auch MySqlExcpetion oder so abfagen
Console.WriteLine("Fehler: " + e.Message); //Jetzt solltest du wissen warum das ganze nicht funktioniert
//Errorhandling
}
Original von ZiMD
string qry = "DELETE FROM wp_users WHERE ID='"+ID+"'"; MySqlCommand teil2 = new MySqlCommand(qry, oMySqlConn); teil2.Prepare();
->Crash
Hm, aber hier sagst du dass es hier einen Crash gibt?
teil2.ExecuteNonQuery(), damit würdest du dann das ganze aus der DB löschen.
Für was machst du überhaupt ein .Prepare()?
Bakunin
try{
string qry = "DELETE FROM wp_users WHERE ID='"+ID+"'";
MySqlCommand teil2 = new MySqlCommand(qry, oMySqlConn);
teil2.Prepare();
catch(System.Exception e){ //du kannst auch MySqlExcpetion oder so abfagen
Console.WriteLine("Fehler: " + e.Message); //Jetzt solltest du wissen warum das ganze nicht funktioniert
//Errorhandling
}
Ähm ich glaube ich weiss was du meinst. Es war mir schon klar, dass dieser Code kein Fehler zurückgibt, da es ja Bent Keck zurückgibt.
Also damit die Reihenfolge stimmt:
public class CustomerTest...
public void testCustomerName() {
Customer customer = new Customer("Bent Keck");
assertEquals("Bent Keck", customer.getName());
}
}
public class Customer...
public Customer(String name) {
}
public String getName() {
return null;
}
}
public class Customer...
public String getName() {
return "Bent Keck";
}
}
So, damit es verständlicher ist.
Was ich jetzt nicht ganz verstehe, wieso diese Schritte durchmachen. Wieso nicht gleich eine Dyn. Lösung machen. Mein Ansatz "fast" ohne zu Denken:
public class CustomerTest{
private string m_Name;
public string Name{
get{ return this.m_Name; }
}
//Oder damit der Methodenaufruf stimmt
public string getName(){
return this.m_Name;
}
}
//frei gecodet, nicht überprüft ;), aber der Inhalt sollte rübergekommen sein
Hallo herbivore,
ich habe den Code herauskopiert und nicht die ganze Klasse abgebildet. Es fehlt der Konstruktor mit einem string Parameter. (ist im fall java code).
Nzgh ich habe die Seite ja komplett vergessen 🙂:
http://www.frankwestphal.de/TestgetriebeneEntwicklung.html
Das Testcode nötig ist, ist mir schon klar. Aber in der Form wie es auf dieser Seite gemacht wird, finde ich es schon ein wenig krass. Darum würde mich eben interessieren ob wirklich viele Leute das ganze so machen.
Und ich habe bis jetzt eignetlich auch noch nie so entwickelt -> Zuerst Testcode, dann der eigentliche Code. Ich mache mir zuerst immer ein UML, designe das ganze durch, solange bis ich denke es passt soweit. Je nach dem, zeige ich es anderen Leuten, damit die Fehler sehen die ich nicht sehe etc.
Und dann entwickle ich nach diesem Design.
Mit der Testgetriebenen Entwicklung, entwickelt man Testcode, und aus den Fehlern die vom Testcode erzeugt werden, erstellt man den eigentlichen Code. (oder habe ich jetzt was falsch verstanden?).
Bakunin
Hallo Leute,
ich habe mir vor kurzem mal NUnit angeschaut und halt auch Testgetriebene Entwicklung. Diese Seite [1] erklärt dass ganze glaub ganz gut.
Aber mich hat das eher abgeschreckt.
Hier ein Beispiel:
public class CustomerTest...
public void testCustomerName() {
Customer customer = new Customer("Bent Keck");
assertEquals("Bent Keck", customer.getName());
}
}
public class Customer...
public String getName() {
return "Bent Keck";
}
}
Ich meine, wenn ich ein math. Problem habe, dann fange ich auch nicht nochmal mit dem 1x1 ein, sondern ein paar Sachen sind einfach schon klar. zB wenn ich einen Taschenrechner entwicklen will, dann gehe ich auch nicht jede mögliche Kombination 2x2 = 4 3x3=9 durch?? Sondern löse es gleich dynamisch. Aber in dieser Anleitung steht eben, dass man Schritt für Schritt alles durchmachen soll, und bewusst Fehler erzeugen soll, etc.
Falls sich jemand mit dem Gebiet auskennt, und/oder es selber anwendet, wäre ich sehr erfreut über eine Erklärung wieso er/sie diese Art der Entwicklung verwendet. Und vorallem, ob man solche Sachen wie oben gezeigt, auch wirklich anwendet.
[1] http://www.frankwestphal.de/TestgetriebeneEntwicklung.html
Bakunin
Ich habe das ganze mal getestet.
Hier der code:
using System;
using System.IO;
using System.Xml.Serialization;
class MainClass
{
public static void Main(string[] args)
{
MeineKlasse x = new MeineKlasse();
x.s_ = "test";
x.i_ = 1000;
TextWriter txt = new StreamWriter("/tmp/datenfile.xml");
XmlSerializer serial = new XmlSerializer(typeof(MeineKlasse));
serial.Serialize(txt, x);
txt.Close();
FileStream fs_read = new FileStream("/tmp/datenfile.xml", FileMode.Open);
MeineKlasse y = (MeineKlasse) serial.Deserialize(fs_read);
fs_read.Close();
}
}
[Serializable]
class MeineKlasse{
private string s;
private int i;
public string s_ { get{ return this.s; } set{ this.s = value; } }
public int i_ { get{ return this.i; } set{ this.i = value; } }
}
dabei bekomme ich folgende Fehlermeldung:
System.InvalidOperationException: MeineKlasse is inaccessible due to its protection level. Only public types can be processed
Ich finde aber nirgends eine Doku in der steht, dass nur öffentliche Klassen serialisiert werden können.
Bakunin
Hallo,
ich versuch mal zu helfen.
In der MSDN steht:
Die XML-Serialisierung ist die Konvertierung der öffentlichen Eigenschaften und Felder eines Objekts in ein serielles Format (in diesem Fall XML) zum Zweck der Speicherung und Übermittlung.
Da also nur öffentliche Eigenschaften und Felder eines Objektes verwendet werden, denke ich, dass die Klasse auch öffentlich sein muss.
BTW es wäre hilfreich die Fehlermeldung zu posten.
Ich hoffe ich konnte helfen,
Bakunin
Danke für die schnellen Antworten!
@Noodles, danke. So kann ich eine Collection erstellen, in dem nur Tag Objekte gespeichert werden dürfen.
@cadi, danke. Das habe ich nicht gewusst... und es klappt 🙂.
Gruß
Bakunin
Hallo Community,
ich habe schon die msdn durchsucht und dieses Forum ebenso. Bin aber nicht wirklich zu einer Lösung gekommen (vielleicht sehe ich aber auch den Wald vor lauter Bäumen nicht mehr).
Das Problem:
public class Tag{
private string m_Name;
private eTagOption m_TagOption = 0;
public string Name{
get{ return this.m_Name; }
set{ this.m_Name = value; }
}
public eTagOption TagOption{
get{ return this.m_TagOption; }
set{ this.m_TagOption = value; }
}
public Tag(){
}
}
public class TagHashtable: System.Collections.Hashtable{
new public Tag this [Object key]{
get{ return ((Tag) base[key]); }
}
}
So. Die new public Tag this[Object key] Methode, habe ich so modifiziert, dass als Rückgabewert ein Tagobjekt geliefert wird.
Soweit so gut, aber wenn ich jetzt in einer Foreach Schleife die Hashtable durchlaufe, möchte ich auch gerne dass man gleich ein Tag Objekt zurückbekommt, anstatt des object Objekt.
Zur zeit durchlaufe ich die Collection so (gibt natürlich auch ein object Objekt zurück):
System.Collections.IEnumerator en = col.Values.GetEnumerator();
while(en.MoveNext()){
Tag oTag = (Tag) en.Current.
...
}
Aber es gibt da ja auch diese Möglichkeit:
foreach(DictonaryEntry oTag in col){
...
}
So, in beiden Fällen muss ich natürlich einen Cast machen.