Pracuję nad formantem, który może przyjmować wiele różnych typów danych (wszystko, co implementuje IComparable).Ogólna konwersja typów bez ryzyka Wyjątki
potrzebuję, aby móc porównać je z innej zmiennej przekazanej w.
Jeśli główny typ danych jest DateTime, a ja przeszedł String, muszę
- próbę przekonwertować Łańcuch do DateTime, aby wykonać porównanie dat.
- jeśli ciąg nie może być przekonwertowany na wartość DateTime, wykonaj porównanie ciągów.
Potrzebuję więc ogólnego sposobu, aby spróbować przekonwertować z dowolnego typu na dowolny typ. Łatwo, .Net zapewnia nam klasę TypeConverter.
Teraz najlepsze, co mogę zrobić, aby ustalić, czy ciąg może zostać przekonwertowany na DateTime, to używać wyjątków. Jeśli ConvertFrom zgłasza wyjątek, wiem, że nie mogę wykonać konwersji i muszę porównać ciąg.
Poniżej jest najlepszy mam:
string theString = "99/12/2009";
DateTime theDate = new DateTime (2009, 11, 1);
IComparable obj1 = theString as IComparable;
IComparable obj2 = theDate as IComparable;
try
{
TypeConverter converter = TypeDescriptor.GetConverter (obj2.GetType());
if (converter.CanConvertFrom (obj1.GetType()))
{
Console.WriteLine (obj2.CompareTo (converter.ConvertFrom (obj1)));
Console.WriteLine ("Date comparison");
}
}
catch (FormatException)
{
Console.WriteLine (obj1.ToString().CompareTo (obj2.ToString()));
Console.WriteLine ("String comparison");
}
Część naszych standardów w stanie roboczym, że:
Wyjątki powinny być podnoszone tylko wtedy, gdy sytuacja Wyjątek - tj. napotkano błąd.
Ale to nie jest sytuacja wyjątkowa. Potrzebuję innego sposobu.
Większość typów zmiennych ma metodę TryParse, która zwraca wartość boolowską, aby umożliwić określenie, czy konwersja się powiodła, czy nie. Ale nie istnieje metoda TryConvert dostępna dla TypeConverter. CanConvertFrom określa tylko, czy możliwa jest konwersja między tymi typami i nie uwzględnia faktycznych danych do przekonwertowania. Metoda IsValid jest również bezużyteczna.
Wszelkie pomysły?
EDIT
Nie mogę korzystać z AS i IS. Nie znam typów danych w czasie kompilacji. Więc nie wiem co do Asa i jest !!!
EDIT
Ok przybity drania. Nie jest tak czysty jak Marc Gravells, ale działa (mam nadzieję). Dzięki za troskę Marc. Będę pracował nad uporządkowaniem go, kiedy znajdę czas, ale mam trochę stosów poprawek, które muszę załatwić.
public static class CleanConverter
{
/// <summary>
/// Stores the cache of all types that can be converted to all types.
/// </summary>
private static Dictionary<Type, Dictionary<Type, ConversionCache>> _Types = new Dictionary<Type, Dictionary<Type, ConversionCache>>();
/// <summary>
/// Try parsing.
/// </summary>
/// <param name="s"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool TryParse (IComparable s, ref IComparable value)
{
// First get the cached conversion method.
Dictionary<Type, ConversionCache> type1Cache = null;
ConversionCache type2Cache = null;
if (!_Types.ContainsKey (s.GetType()))
{
type1Cache = new Dictionary<Type, ConversionCache>();
_Types.Add (s.GetType(), type1Cache);
}
else
{
type1Cache = _Types[s.GetType()];
}
if (!type1Cache.ContainsKey (value.GetType()))
{
// We havent converted this type before, so create a new conversion
type2Cache = new ConversionCache (s.GetType(), value.GetType());
// Add to the cache
type1Cache.Add (value.GetType(), type2Cache);
}
else
{
type2Cache = type1Cache[value.GetType()];
}
// Attempt the parse
return type2Cache.TryParse (s, ref value);
}
/// <summary>
/// Stores the method to convert from Type1 to Type2
/// </summary>
internal class ConversionCache
{
internal bool TryParse (IComparable s, ref IComparable value)
{
if (this._Method != null)
{
// Invoke the cached TryParse method.
object[] parameters = new object[] { s, value };
bool result = (bool)this._Method.Invoke (null, parameters);
if (result)
value = parameters[1] as IComparable;
return result;
}
else
return false;
}
private MethodInfo _Method;
internal ConversionCache (Type type1, Type type2)
{
// Use reflection to get the TryParse method from it.
this._Method = type2.GetMethod ("TryParse", new Type[] { type1, type2.MakeByRefType() });
}
}
}
Niezupełnie, istnieje kwestia wie co typ ma być przekształcony. Tutaj nie. Odpowiedź na to pytanie w ogóle mi nie pomaga. –
Dobrze. Słusznie. – jason
Uff ... Myślałem, że mam zamiar zamknąć moje pytanie. Spędziłem wiele godzin na tym .. ;-) –