Autor Beitrag
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Fr 13.12.13 23:35 
Moin,


ich meine mich zu erinnern, dass es die Möglichkeit gibt, der Convert.ChangeType (oder Andere) vorzuschreiben, wie sie konvertieren soll. Ich weiß bloß nicht mehr, wie das ging und über Google hab ich auch nichts funktionierendes gefunden.

Ich hab bisher versucht, den jeweiligen Methoden von Convert einen eigenen FormatProvider mit zugeben, bloß wird der scheinbar komplett ignoriert. Ich hab in die GetFormat-Methode des Providers einen Breakpoint gesetzt und fest gestellt, dass die überhaupt nicht aufgerufen wird, dennoch bekomme ich eine InvalidCastException:

Zitat:
Ungültige Umwandlung von "DateTime" in "Int32".


Ich möchte aber nun einmal DateTime zu int (und umgekehrt) konvertieren, auf eine ganz eigene Art und Weise, bloß lässt der das scheinbar nicht zu.

ausblenden C#-Quelltext
1:
2:
3:
var result = (int)Convert.ChangeType(DateTime.Now, typeof(int), new MyGreatFormatProvider());
// oder so, beides der selbe Fehler:
var result = Convert.ToInt32(date, new MyGreatFormatProvider());


Hab ich zu so später Stunde einen totalen Denkfehler und sehe den Wald vor lauter Bäumen nicht, oder habe ich mich von Anfang an geirrt und es gibt diese Möglichkeit gar nicht?

Zur Not nehme ich auch einfach den Provider und lasse den direkt konvertieren, die Methode ist ja da, aber ich würde es gerne erreichen, dass ich das zentral über die Convert-Klasse regeln kann.


Würde mich schon über ein bisschen Hilfe freuen ^^
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 15.12.13 02:06 
Hallo!

Wenn ich die Remarks hier richtig lese, kannst Du mit einem IFormatProvider keine eigene Konvertierung zwischen DateTime und int erzwingen, da keine der beiden Fälle zutrifft, in denen der Provider benutzt wird.

Ansonsten kenne ich keine Möglichkeit, das zu beeinflussen :nixweiss:

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: So 15.12.13 02:23 
Convert leitet das nur an den Typ weiter (sind ja alles IConvertibles die in Convert zusammengefasst sind) und ToInt32 in DateTime sieht so aus.

ausblenden C#-Quelltext
1:
2:
3:
4:
int IConvertible.ToInt32(IFormatProvider provider)
{
    throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo"new object[] { "DateTime""Int32" }));
}
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mo 16.12.13 17:38 
Da es das so wie ich mir das vorgestellt habe, scheinbar nicht gibt, hab ich mir jetzt einfach eine Klasse geschrieben, wo das dann abgewickelt wird, wie ich mir das gewünscht habe.

Ich habe aber auch gefunden, wo ich das her habe und zwar kam das von WPF, wo es das Interface IValueConverter. So hab ich das auf Arbeit mal gesehen, hab es eben wieder gefunden.
Über die Zeit hab ich mir da wohl mehr zusammen gedacht, als da war ^^


Aber dennoch danke für die Hilfe ^^
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mo 16.12.13 17:46 
Datetime nach Integer zu konvertieren macht wenig Sinn, denn die Zeit (der Bruchteil nach dem Komma) würde komplett wegfallen. Dann kannst Du gleich Trunc nehmen, um eine Integer zu erzeugen, denn bei der Umwandlung erhältst Du eh nur die Tagesinformation zurück.

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 16.12.13 18:41 
Für den Fall das es generisch sein soll, also Quell und/oder Zieltyp nicht fix sind, dann könnte man einen TypeConverter schreiben um ihn dann via

ausblenden C#-Quelltext
1:
Int32 x = (Int32)TypeDescriptor.GetConverter(typeof(DateTime)).ConvertTo(meinLieberDateTime, typeof(Int32));					


zu verwenden. Wenn du aber nur genau diese eine Konvertierung hast ist das Overkill. Genauso wie ein IValueConverter.
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mo 16.12.13 18:49 
Die Konvertierung zwischen Int und DateTime hin und her ist ein ganz eigener Fall, der außerhalb meines Projektes tatsächlich keinen Sinn ergibt.



@Ralf:

Genau das war der Plan ^^
Vielleicht auch noch etwas abstrakter, da bin ich noch am überlegen.

Dass es overkill ist, stört mich auch gar nicht, da ich mir das dann extra abspeichere und so dann wieder verwenden kann.
Wirklich viel hab ich noch nicht gesammelt, aber sowas kann ich dann ja irgendwann mal in eine große DLL zusammen legen und so immer zentral nutzen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 16.12.13 21:13 
Zitat:
Vielleicht auch noch etwas abstrakter, da bin ich noch am überlegen.


Abstrakter? Ich bin ITler und habe eine spezielle Vorstellung von abstrakt und die passt hier irgendwie nicht. Was meinst du?
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mo 16.12.13 22:14 
Was ich meine ist, dass sich der globale TypeConverter die einzelnen Converter-Implementierungen selber via Reflection zusammen sucht.

Ich habs auf Arbeit an einem relativ langsamen PC bei einem Projekt mit rund 10500 Klassen gemessen, wie lange das dauert.
Ergebnis waren rund 350 ms, also deutlich schneller als ich erwartet hätte.

So kann ich dann z.B. auch Objekte konvertieren, wo der Typ erst zur Laufzeit fest steht, weil ich den passenden Converter nicht mehr kennen muss. Wenn der aber bekannt ist, wird der halt vor gegeben und dann auch genutzt.


Problematisch wird es nur, wenn sich zwei Converter in die Quere kommen, weil sie beide passen würden.
Da muss ich mir noch aus denken, welcher dann gewählt wird, aber ich glaube, bevor ich aus einem Converter jetzt eine hoch komplexe Klasse mache, mit vielen Eigenschaften und Co, die verschiedene Bedingungen vor geben, nehme ich einfach FirstOrDefault und biete die Möglichkeit an, alle Passenden abzufragen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 16.12.13 22:49 
Das was du beschreibst ist ziemlich genau das was TypeDescriptor.GetConverter bereits tut, vermutlich nur ohne Reflection. Die Klassen die ein TypeConverterAttribute tragen werden sich vermutlich in irgendeine Art von Dictionary des TypeDescriptor eintragen bzw. wenn man einen TypeConverter für einen bereits existierenden Typen braucht (wie hier für DateTime und Int32) den per TypeDescriptor.AddAttributes in diesem Dictionary nachtragen.

Edit:ok kein Dictionary sondern eine WeakHashtable. Ich war aber nah dran.
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mo 16.12.13 23:10 
[meta]Also gibts das doch schon, nur ein kleines bisschen anders umgesetzt.

Was ich mich dann aber frage: Wie trägt sich ein neuer Converter selber ein?
Geht das überhaupt? Ich meine, das geht nicht.

Was mir so einfallen würde, wäre eine Zeile im statischen Konstruktor, der den Typ dort einträgt. Allerdings wird der nicht automatisch beim Programm-Start aufgerufen, sondern erst später, spätestens vor der ersten Nutzung dieser Klasse. Das würde also bedeuten, dass ein Converter zur Laufzeit eventuell noch nicht bekannt ist, wenn er gesucht wird.
So funktioniert das also nicht und alles nicht statische funktioniert auch nur, wenn irgendwann im Verlauf des Programms bewusst diese Converter entsprechend eingetragen werden, was dann aber auch doof ist, weil dann zu Beginn, also eigentlich zur Entwicklungszeit, alle Converter bekannt sein müssten und das geht an dem/meinem Ziel vorbei.

Ich denke, dass das genauso mit Reflection arbeitet. Nur wird hier zuerst nach einem passenden Attribut gesucht.[/meta]Hab deinen Post nochmal gelesen und fest gestellt, dass ich da wohl den Teil mit TypeDescriptor.AddAttributes überlesen habe. :D
(Wer es doch lesen will, bei mir funzt das mit dem Meta nicht ganz, über die Zitat-Funktion sollte man es aber lesen können)


Stimmt, im Prinzip genau das, was ich gesucht habe und dann selber umsetzen wollte. :D
Danke für den wohl eher zufälligen Tipp ^^
Aber ich glaube, für meinen ursprünglichen Anwendungszweck ist das doch eher unpassend. Aber interessant, das zu kennen. ^^


PS:

Was genau ist denn eine WeakHashtable?


Zuletzt bearbeitet von Palladin007 am Mo 16.12.13 23:33, insgesamt 5-mal bearbeitet
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 16.12.13 23:24 
Zitat:
Was genau ist denn eine WeakHashtable?


Bin ich beim Browsen über den TypeDescriptor Code drüber gestolpert ist also irgendwas internes. Der Sinn warum nicht eine einfache HashTable hat sich mir auch nicht erschlossen. Eine HashTable die WeakReferences verwaltet macht an der Stelle eigentlich wenig Sinn. Vom Namen auf das was sie tut zu schließen hilft also nicht ;)
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mo 16.12.13 23:28 
Ich musste erst einmal nach lesen, was genau nochmal der Unterschied zwischen einer HashTable und einem Dictionary ist. :D


PS:
Hab auch mal den Kram, den ich geschrieben habe, hinter einem von diesen Meta-Ausrufezeichen, versteckt, weil das nach einem erneuten lesen deines letzten Beitrages irgendwie überflüssig wurde. :D