Saya XmlReader
mem -parsing file XML dengan kelas di .NET dan saya pikir akan pintar menulis fungsi parse umum untuk membaca atribut yang berbeda secara umum. Saya datang dengan fungsi berikut:
private static T ReadData<T>(XmlReader reader, string value)
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
}
Saat saya menyadari, ini tidak bekerja sepenuhnya seperti yang saya rencanakan; itu melontarkan kesalahan dengan tipe primitif seperti int
atau double
, karena cast tidak dapat mengonversi dari tipe a string
ke numerik. Apakah ada cara agar fungsi saya berlaku dalam bentuk yang dimodifikasi?
Sudahkah Anda mencoba Convert.ChangeType ?
Jika metode selalu mengembalikan string, yang menurut saya aneh, tetapi itu bukan intinya, mungkin kode yang diubah ini akan melakukan apa yang Anda inginkan:
private static T ReadData<T>(XmlReader reader, string value) { reader.MoveToAttribute(value); object readData = reader.ReadContentAsObject(); return (T)Convert.ChangeType(readData, typeof(T)); }
sumber
mencoba
if (readData is T) return (T)(object)readData;
sumber
Anda dapat meminta tipe menjadi tipe referensi:
private static T ReadData<T>(XmlReader reader, string value) where T : class { reader.MoveToAttribute(value); object readData = reader.ReadContentAsObject(); return (T)readData; }
Dan kemudian lakukan yang lain yang menggunakan tipe nilai dan TryParse ...
private static T ReadDataV<T>(XmlReader reader, string value) where T : struct { reader.MoveToAttribute(value); object readData = reader.ReadContentAsObject(); int outInt; if(int.TryParse(readData, out outInt)) return outInt //... }
sumber
Sebenarnya, masalah di sini adalah penggunaan ReadContentAsObject. Sayangnya, metode ini tidak memenuhi harapannya; sementara itu harus mendeteksi jenis yang paling tepat untuk nilai, itu sebenarnya mengembalikan string, tidak peduli apa (ini dapat diverifikasi menggunakan Reflector).
Namun, dalam kasus spesifik Anda, Anda sudah tahu tipe yang ingin Anda gunakan, oleh karena itu saya akan mengatakan Anda menggunakan metode yang salah.
Coba gunakan ReadContentAs sebagai gantinya, itulah yang Anda butuhkan.
private static T ReadData<T>(XmlReader reader, string value) { reader.MoveToAttribute(value); object readData = reader.ReadContentAs(typeof(T), null); return (T)readData; }
sumber
Anda mungkin dapat mengirimkan, sebagai parameter, delegasi yang akan mengkonversi dari string ke T.
sumber
Tambahkan batasan 'class' (atau lebih detail, seperti class dasar atau antarmuka objek T yang Anda pilih):
private static T ReadData<T>(XmlReader reader, string value) where T : class { reader.MoveToAttribute(value); object readData = reader.ReadContentAsObject(); return (T)readData; }
atau
where T : IMyInterface
atauwhere T : new()
, dllsumber
Sebenarnya, tanggapan tersebut memunculkan pertanyaan yang menarik, yaitu apa yang Anda ingin fungsi Anda lakukan jika terjadi kesalahan.
Mungkin akan lebih masuk akal untuk membangunnya dalam bentuk metode TryParse yang mencoba membaca menjadi T, tetapi mengembalikan false jika tidak dapat dilakukan?
private static bool ReadData<T>(XmlReader reader, string value, out T data) { bool result = false; try { reader.MoveToAttribute(value); object readData = reader.ReadContentAsObject(); data = readData as T; if (data == null) { // see if we can convert to the requested type data = (T)Convert.ChangeType(readData, typeof(T)); } result = (data != null); } catch (InvalidCastException) { } catch (Exception ex) { // add in any other exception handling here, invalid xml or whatnot } // make sure data is set to a default value data = (result) ? data : default(T); return result; }
edit: sekarang setelah saya memikirkannya, apakah saya benar-benar perlu melakukan tes convert.changetype? bukankah garis as sudah mencoba melakukan itu? Saya tidak yakin bahwa melakukan pemanggilan changetype tambahan itu benar-benar menyelesaikan apa pun. Sebenarnya, ini mungkin hanya meningkatkan overhead pemrosesan dengan menghasilkan pengecualian. Jika ada yang tahu perbedaan yang membuatnya layak dilakukan, silakan posting!
sumber