大きな絵:
私はRazorの制限のように見えるものを見つけました、そして私はそれを回避する良い方法を思い付くのに苦労しています。
プレーヤー:
私がこのようなモデルを持っているとしましょう:
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;
}
}
}
そして、このようなサブクラス:
public class MyFooModel : BaseFooModel<MyBarType>
{
// ...
}
public class MyBarType : BaseBarType
{
// ...
}
MyFooModel
次のように定義されているかみそりのビューに渡せるようにしたいと思います。
// FooView.cshtml
@model BaseFooModel<BaseBarType>
しかし、それはうまくいきません。FooView
期待しているBaseFooModel<BaseBarType>
が取得するという実行時エラーが発生しますMyFooModel
。MyFooModel
からの継承とからBaseFooModel<MyBarType>
のMyBarType
継承を思い出してくださいBaseBarType
。
私が試したこと:
私はこれをかみそり以外の土地で試して、同じことが当てはまるかどうかを確認しました。ビューを機能させるには、ビューでテンプレートパラメータを使用する必要がありました。これがその非かみそりの見方です:
public class FooView<T>
where T : BaseBarType
{
BaseFooModel<T> Model;
public FooView(BaseFooModel<T> model)
{
Model = model;
}
}
その構造では、以下が機能します。
new FooView<MyBarType>(new MyFooModel());
私の質問:
どうすればRazorでそれを行うことができますか?どうすれば私がやっているようなタイプを渡すことができFooView
ますか?
できませんが、これを回避する方法はありますか?どういうわけか同じアーキテクチャを実現できますか?
さらに情報を提供できるかどうか教えてください。.NET4とMVC3を使用しています。
編集:
今のところ、のサブクラスごとにかみそりのビューを追加していますBaseFooModel<BaseBarType>
。新しいモデルを追加するたびに新しいビューを作成する必要がないので、私はそれについては気になりません。
もう1つのオプションは、これを通常のc#クラスでかみそりなしで機能させることができるという事実を利用することです。かみそり@inherits
にc#ビューを表示させてから、renderメソッドを呼び出すことができます。HTMLをレンダリングする2つの方法が好きではないので、このオプションは嫌いです。
他のアイデアはありますか?Foo
とでクラス名を付けると、問題のコンテキストを理解するのが難しいことはわかっていますBar
が、少し機密性が高いため、あまり多くの情報を提供することはできません。それについてお詫び申し上げます。
ベンジャミンの答えを使って、私がこれまでに持っているもの:
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
{
// ...
}
何がうまくいったのか:
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
{
// ...
}