The Big Picture:Passo sottoclasse di modello generico di vista rasoio
ho trovato quello che sembra una limitazione del Razor e sto avendo problemi a venire con un buon modo intorno ad esso.
I Giocatori:
Diciamo che ho un modello come questo:
public abstract class BaseFooModel<T>
where T : BaseBarType
{
public abstract string Title { get; } // ACCESSED BY VIEW
public abstract Table<T> BuildTable();
protected Table<T> _Table;
public Table<T> Table // ACCESSED BY VIEW
{
get
{
if (_Table == null)
{
_Table = BuildTable();
}
return _Table;
}
}
}
E una sottoclasse come questo:
public class MyFooModel : BaseFooModel<MyBarType>
{
// ...
}
public class MyBarType : BaseBarType
{
// ...
}
voglio essere in grado di passare MyFooModel
in una vista del rasoio che è definita in questo modo:
// FooView.cshtml
@model BaseFooModel<BaseBarType>
Ma, questo non funziona. Ottengo un errore in fase di esecuzione dicendo che FooView
si aspetta BaseFooModel<BaseBarType>
ma ottiene MyFooModel
. Ricordiamo che MyFooModel
in herits da BaseFooModel<MyBarType>
e MyBarType
eredita da BaseBarType
.
quello che ho provato:
ho provato questo in terreni non rasoio per vedere se lo stesso è vero, che è. Ho dovuto usare un parametro template nella vista per farlo funzionare. Ecco questo punto di vista non rasoio:
public class FooView<T>
where T : BaseBarType
{
BaseFooModel<T> Model;
public FooView(BaseFooModel<T> model)
{
Model = model;
}
}
Con tale struttura, il seguente funziona:
new FooView<MyBarType>(new MyFooModel());
La mia domanda:
Come posso farlo con Razor ? Come posso passare un tipo come sto facendo con FooView
?
Non riesco a, ma c'è un modo per aggirare questo? Posso ottenere la stessa architettura in qualche modo?
Fammi sapere se posso fornire ulteriori informazioni. Sto utilizzando .NET 4 e MVC 3.
EDIT:
Per ora, sto solo aggiungendo una vista rasoio per ogni sottoclasse di BaseFooModel<BaseBarType>
. Non ne sono entusiasta perché non voglio creare una nuova vista ogni volta che aggiungo un nuovo modello.
L'altra opzione è sfruttare il fatto che I am è in grado di farlo funzionare in normali classi C# senza rasoio. Potrei avere il mio rasoio vista @inherits
la vista C# e quindi chiamare qualche metodo di rendering. Non mi piace questa opzione perché non mi piace avere due modi di renderizzare html.
Altre idee?So che è difficile capire il contesto del problema quando sto dando nomi di classe con Foo
e Bar
, ma non posso fornire troppe informazioni poiché è un po 'sensibile. Le mie scuse su questo.
Quello che ho finora, con la risposta di Benjamin:
public interface IFooModel<out T>
where T : BaseBarModel
{
string Title { get; }
Table<T> Table { get; } // this causes an error:
// Invalid variance: The type parameter 'T' must be
// invariantly valid on IFooModel<T>.Table.
// 'T' is covariant.
}
public abstract class BaseFooModel<T> : IFooModel<T>
where T : BaseBarModel
{
// ...
}
Che ha finito per lavoro:
public interface IFooModel<out T>
where T : BaseBarModel
{
string Title { get; }
BaseModule Table { get; } // Table<T> inherits from BaseModule
// And I only need methods from BaseModule
// in my view.
}
public abstract class BaseFooModel<T> : IFooModel<T>
where T : BaseBarModel
{
// ...
}
molto spesso trovo una risposta per il momento ho digitato la questione, o almeno poco dopo. non questa volta ... – lbstr
qual è il tuo BaseFooModel - e cosa fa sulla pagina (inserimenti, solo visualizzazione, è cambiato, ecc.)? questo è rilevante (qualche codice di esempio) – NSGaga
Questo è un buon punto, ma direi che dato che questa informazione viene usata in una vista, dovrebbe solo essere letta. Qualsiasi aggiornamento dovrebbe accadere in un metodo di azione del controllore. –