Domanda

Al momento sto lavorando su una domanda in cui ho bisogno di caricare i dati da un database SQL e quindi assegnare i valori recuperati nelle proprietà di un oggetto. Sto facendo questo utilizzando riflessione dal momento che i nomi delle proprietà e delle colonne sono gli stessi. Tuttavia, molte delle proprietà utilizzano un tipo struct personalizzato che è fondamentalmente un involucro di valuta per il tipo decimale. Ho definito una conversione implicita nel mio struct:

public static implicit operator Currency(decimal d)
{
     return new Currency(d);
}

Questo funziona bene quando lo uso nel codice. Tuttavia, quando ho questo:

foreach (PropertyInfo p in props)
{
     p.SetValue(this, table.Rows[0][p.Name], null);
}

Si genera un ArgumentException affermando che non è possibile convertire da System.Decimal alla valuta. Sono confuso dal momento che funziona bene in qualsiasi altra circostanza.

È stato utile?

Soluzione

I pensare è necessario prima Unbox il valore in table.Rows[0][p.Name] come decimal.

In altre parole:

foreach (PropertyInfo p in props)
{
     if (p.PropertyType == typeof(Currency))
     {
         Currency c = (decimal)table.Rows[0][p.Name];
         p.SetValue(this, c, null);
     }
     else
     {
         p.SetValue(this, table.Rows[0][p.Name], null);
     }
}

Questo è un problema che ho visto un paio di volte prima, così ho effettivamente deciso di scrivere un post su di esso . Qualcuno alla ricerca di un po 'più spiegazione, sentitevi liberi di dare una lettura.

Altri suggerimenti

Sfortunatamente, questi operatori di conversione definite dall'utente non vengono utilizzati dal runtime; sono utilizzati solo dal compilatore in fase di compilazione. Quindi, se si prende una decimal fortemente tipizzato e assegnarlo a un Currency fortemente tipizzato, il compilatore inserirà una chiamata al operatore di conversione e felice di tutti. Tuttavia, quando si chiama SetValue come si sta facendo qui, il runtime si aspetta di dare un valore del tipo appropriato; il runtime non ha idea che esista questo operatore di conversione, e non potrà mai chiamarlo.

Presumo che table è di tipo DataTable nel codice, quindi il primo indicizzatore restituisce un DataRow, e il secondo restituisce un object. Poi prende PropertyInfo.SetValue anche un object come secondo argomento. In nessun posto in questo codice un cast accade nel codice , motivo per cui l'operatore di conversione di overload non viene applicata.

In linea generale, si applica solo quando i tipi statici sono noti (dimenticando dynamic in C # 4.0 per il momento). Esso non si applica quando la boxe e le cose unboxing. In questo caso, l'indicizzatore su scatole DataRow è il valore, e cerca PropertyInfo.SetValue di unboxing ad un diverso tipo -. E non riesce

Mentre io non rispondo il problema, credo che in questo tipo di situazione, sarebbe più opportuno utilizzare un quadro ORM come Entity Framework o NHibernate che mappare le tabelle nei vostri oggetti di dominio e di gestire tutte le conversioni per voi . Usando qualcosa come riflessione per capire cosa i campi da compilare un oggetto di dominio è un modo lento per farlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top