12

これは可能ですか?これが私が試していることです:

    public ActionResult Index()
    {
        dynamic p = new { Name = "Test", Phone = "111-2222" };
        return View(p);
    }

そして、私のビューはSystem.Web.Mvc.ViewPage<dynamic>Model.Nameを継承し、それを出力しようとします。

エラーが発生しました:'<> f__AnonymousType1.Name'は、保護レベルが原因でアクセスできません

それで、基本的に、私がやろうとしていることは不可能ですか?なぜまたはなぜそうではないのですか?

更新:これが私の見解です

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<asp:Content ...>
    <%=Model.Name%>
    <%=Model.Phone%>
</asp:Content>

Viewコンストラクターはフレームワークに組み込まれています。

4

4 に答える 4

7

匿名タイプはメソッドで返すことはできません。それらは、それらが定義されているメソッドの範囲内でのみ有効です。

以前に定義したModelクラスを使用して、それをビューに渡す必要があります。すべてのフィールドが定義されていないModelクラスを渡すことに問題はありません。

更新

以前は間違っていたと思います。これは機能するはずです。おそらく、問題はビュー内にあります。もっとコードを投稿できますか?特にビューとそのコンストラクター。

2番目を更新します。

わかりました。動的変数として使用するために匿名型を別のメソッドに渡すことについては間違っていました。これは可能です。

しかし、私はあなたがやろうとしていることがうまくいくと信じていたのも間違っていました。残念ながら、そうではありません。問題は、内部ViewPage<TModel>でを使用するを使用していることです。ViewDataDictionary<TModel>強力な型が必要なため、動的オブジェクトを使用することはできません。内部構造は内部で動的を使用せず、型が失敗するときに動的を指定します。

必要なのは、動的として内部的にそれを受け入れて格納DynamicViewPageするクラスと対応するクラスです。次に、匿名タイプを使用して、それをビューに渡すことができます。DynamicViewDataDictionaryobject

そうは言っても、あなたは何も得られないでしょう。行ったように(つまり)ビューを指定することはできますが<%=Model.Name%>、強い型付けのメリットはありません。インテリセンスはなく、型安全性もありません。ViewDataDictionary@Dennis Palmerが提案するように、型なしを使用するのも同様です。

これは興味深い(そして、残念ながら私にとっては吸収的な)思考実験でしたが、最終的には、それは起こらないと思います。パブリックタイプを宣言してビューに渡すか、型なしディクショナリを使用します。

于 2009-07-24T17:22:50.707 に答える
7

ここで動的型を使用することで、どのような利点を得たいと考えていましたか?

ViewData ディクショナリを使用すると、ビュー出力に任意のオブジェクト/アイテムを簡単に追加できます。

ビュー内のプロパティ名を取得するためにリフレクションは必要ありません。ViewData.Keys名前のコレクションを取得するために使用するだけです。

編集:私は自分自身でダイナミクスについてもう少し学びました。おそらく、DynamicObjectから継承する独自の動的オブジェクト クラスを作成する必要があると思います。そのクラスにプライベート ディクショナリを用意してから、 and をオーバーライドする必要がTrySetMemberありTryGetMemberます。

編集はさておき:強く型付けされた ViewModel の利点の 1 つは、POST Action メソッドのパラメーターとして受け入れることができることだと思います。MVC フレームワークはモデル バインディングを処理し、アクション メソッドには ViewModel クラスのインスタンスを設定するだけです。たとえ機能したとしても、ダイナミックでその利点があるとは思いません。

編集結果: DynamicObject から派生したクラスを使用してみましたが、ビューをレンダリングしようとすると VS2010 がクラッシュします。例外は発生しません。ハード クラッシュと Visual Studio の再起動だけです。これが、クラッシュの原因となる私が思いついたコードです。

カスタム動的クラス:

public class DynViewModel : DynamicObject
{
    private Dictionary<string, object> ViewDataBag;
    public DynViewModel()
    {
        this.ViewDataBag = new Dictionary<string, object>();
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        this.ViewDataBag[binder.Name] = value;
        return true;
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = this.ViewDataBag[binder.Name];
        return true;
    }
}

コントローラーで:

public ActionResult DynamicView()
{
    dynamic p = new DynamicViewModel.Models.DynViewModel();
    p.Name = "Test";
    p.Phone = "111-2222";

    return View(p);
}

私の見解は、基本的に質問に記載されているものと同じです。

<p>Name: <%=Model.Name %></p>
<p>Phone: <%=Model.Phone %></p>

私の結論:これはうまくいくかもしれませんが、VS2010 の Beta 1 では、私のコードが原因で Visual Studio がクラッシュする理由がわかりません。VS2010 Beta 2 がリリースされたら、ダイナミクスを学ぶ上で興味深い演習になるので、もう一度試してみます。ただし、これが機能したとしても、ViewData ディクショナリを使用する利点はまだありません。

フィル・ハークが助けに!これは、Phil Haack によるブログ投稿です。それはあなたが探していたもののようです。メソッド Missing と C# 4 の楽しみ方

于 2009-07-24T17:41:02.447 に答える
1

.NET 4.0では、匿名型をExpandoObjectsに簡単に変換できるため、変換自体のオーバーヘッドですべての問題が修正されます。ここをチェックしてください

于 2011-04-14T23:40:26.250 に答える
1

ここでの実際のエラー(<>f__AnonymousType1.Name' is inaccessible due to its protection level)は、匿名型を使用した結果です。匿名型は暗黙的internalに(少なくともC#では)使用されるため、通常は同じアセンブリからのみアクセスできます。ビューは実行時に別のアセンブリinternalにコンパイルされるため、 匿名型にアクセスできません。

解決策は、具体的/名前付きクラスをモデルとしてビューに渡すことです。必要に応じて、ビュー自体を引き続き使用dynamicできます。

于 2011-03-31T15:35:24.850 に答える