2011-12-19 6 views
5

Sto usando ASP.NET MVC3 e mi chiedo che il modelbinder predefinito si leghi alle proprietà pubbliche ma non ai campi pubblici.C'è un motivo per cui il modelbinder predefinito non si lega ai campi?

Normalmente ho appena definito le classi del modello con proprietà ma a volte uso alcune classi predefinite che contengono alcuni campi. E ogni volta devo fare il debug e ricordare che il modelbinder non apprezza i campi.

La domanda: qual è la ragione?

risposta

0

Forse il motivo per ignorare i campi è aumentare le prestazioni del raccoglitore. Invece di cercare tutti i campi e le proprietà. Il modello Binder cerca solo proprietà.

Anche se penso che Model Binder utilizzi la cache per migliorare le prestazioni.

2

ma a volte faccio uso di classi predefinite che contiene alcuni campi

Mentre non posso rispondere alla tua domanda circa il motivo esatto per cui il legante modello predefinito funziona solo con proprietà (la mia ipotesi è che si rispetti meglio incapsulamento in questo modo ed evita di modificare lo stato interno dell'oggetto che è quello che rappresentano i campi) Posso dire che quelle che chiamate classi predefinite dovrebbero normalmente essere i modelli di vista. Dovresti sempre utilizzare i modelli di visualizzazione da e verso le azioni del tuo controller. Quei modelli di vista sono classi che sono specificatamente definite per soddisfare i requisiti della vista data.

Torna al punto principale: i campi devono essere modificati solo all'interno della classe data. Non dovrebbero essere accessibili direttamente dall'esterno. Rappresentano e mantengono lo stato interno della classe. Le proprietà d'altra parte sono ciò che dovrebbe essere esposto al mondo esterno. Immagina che nella proprietà getter/setter tu avessi qualche logica personalizzata. Modificando direttamente il campo questa logica personalizzata verrebbe interrotta e potenzialmente porterebbe l'oggetto in uno stato incoerente.

+1

Ok, ma per questo avete i modificatori di accesso. Se non voglio che un campo sia impostato direttamente, lo dichiaro semplicemente 'privato'. Le classi Viewmodel sono normalmente solo datacontainer e per lo più non contengono molta logica, quindi ho pensato che fosse giusto usare solo i campi pubblici. – Jan

+0

@Jan, normalmente i campi devono essere privati. –

+1

E normalmente non dovresti avere una logica nei getter delle proprietà ... – gdoron

0

DefaultModelBinder espone un metodo pubblico: DefaultModelBinder.BindModel e un numero di metodo protetto disponibile per l'override. Tutti elencati nell'elenco here.

Oltre al modello, questi metodo riferiscono alle proprietà solo, non campi, come

  • GetModelProperties,
  • GetFilteredModelProperties,
  • GetPropertyValue,
  • OnXYZValidating,
  • OnXYZValidated,
  • OnXYZUpdating,
  • OnXYZUpdated,
  • GetXYZValue,

dove XYZ sta per entrambi i Model, o Property/ies, o entrambi, e così via.

Come potete vedere, non vi è alcuno Fields menzionato con questi nomi. Come Darin spiegato, nessuna modifica diretta allo stato del modello è tollerata dal Raccoglitore. Quindi no Field nei suoi metodi.

E inoltre, si potrebbe desiderare di dare un'occhiata a un'altra classe importante: ModelBindingContext. Un'istanza di questa classe viene passata allo BindModel, e successivamente a BindSimpleModel, e BindComplexModel, a seconda del tipo di modello (string, int, ... sono considerati semplici, tutto il resto è complesso).

Quindi, questo contesto ha le seguenti proprietà:

  • ModelXYZ, e
  • PropertyXYZ.

In altre parole, non è possibile fare riferimento ai campi nel ViewModel a meno che non si ignorino queste classi e si intraprendano azioni speciali per farlo.

Ma ancora, attenzione a combattere il framework, è sempre più facile seguirlo.

MODIFICA: La classe ModelMetadata contiene tutti i dati necessari per associare il modello. Il suo codice tuttavia non mostra alcun segno di campi, nomi di campi, ecc. Solo le proprietà sono referenziate e accessibili. Quindi, anche se si tenta di ereditare e sovrascrivere DefaultModelBinder e ModelBinderContext, ancora non sarà in grado di accedere fiellds, non importa quale sia il loro modificatore di accesso è: pubblico, privato, ecc

Spero che questo spiega la maggior parte di esso.