web-dev-qa-db-ja.com

匿名型から値を取得する

私は次のような方法があります:

_public void MyMethod(object obj){

  // implement

}
_

そして私はそれをこのように呼びます:

_MyMethod(new { myparam= "waoww"});
_

では、どうすればMyMethod()を実装してmyparam値を取得できますか?

編集

私はこれを使用します:

_dynamic d= obj; 
string param = d.myparam; 
_

しかし、エラーが発生します:

_'object' does not contain a definition for 'myparam' 
_

また、ブレークポイントを使用すると、dにmyparamstringプロパティがあることがわかります。

そして、動的タイプをチェックして、次のようなプロパティが含まれているかどうかを確認する方法はありますか?

_if(d.contain(myparam))?
_

編集II

これは私のメインコードです:

_public static MvcHtmlString SecureActionLink(this HtmlHelper htmlHelper, 
         string linkText, string actionName, string controllerName, 
         object routeValues, object htmlAttributes) {


    string areaName = 
         (string)htmlHelper.ViewContext.RouteData.DataTokens["area"];

        dynamic areaObject = routeValues;

        if(areaObject != null && !string.IsNullOrEmpty(areaObject.area))
            areaName = areaObject.area;

// more
}
_

そしてそれを次のように呼びます:

_<p>@Html.SecureActionLink("Secure Link between Areas", "Index", "Context", 
                          new { area = "Settings" }, null)</p>
_

そしてエラーは:

_Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a
 definition for 'area'

 Line 303:  dynamic areaObject = routeValues;
 Line 304:
 Line 305:  if(areaObject != null && !string.IsNullOrEmpty(areaObject.area))
 Line 306:      areaName = areaObject.area;
 Line 307:

 Source File: D:\Projects\MyProject\HtmlHelpers\LinkExtensions.cs    Line: 305 
_

編集III

これは、HtmlHelper定義のAssemblyInfoです。

_[Assembly: AssemblyTitle("MyProject.Presentation")]
[Assembly: InternalsVisibleTo("cpanel.MyProject.dev")]
_

しかし、まだエラーがあります:_'object' does not contain a definition for 'area'_異なるアセンブリを使用していますが、ブレークポイントを使用すると、動的なareaobjectareanameプロパティがあります。その値を見ることができますが、エラーは次のように言います:_'object' does not contain a definition for 'area'_どうすればそれが可能か理解できませんか?

編集

アセンブリを変更すると、動的タイプが内部になりましたが、エラーは以前と同じままです

16
Saeid

これを使用してください:

string area = areaObject.GetType().GetProperty("area").GetValue(areaObject, null);
30
Saeid

C#4を使用している場合は、動的型付けを使用できます。

public void MyMethod(object obj) {
    dynamic d = obj;
    Console.WriteLine(d.myparam);
}

しかし、なぜ名前付きタイプを使用していないのかという疑問が生じます。匿名タイプは、このような異なるメソッド間で共有されるようには実際には設計されていません。

編集:これがオブジェクトを作成する元のコードとは異なるアセンブリにある場合、匿名タイプは内部であるため、 [InternalsVisibleTo] を使用する必要があることに注意してください。

24
Jon Skeet

まず、他の人が言っているように、そもそもこれをしないでください。これは、匿名タイプの使用を意図した方法ではありません。

第二に、あなたがそれをすることに傾倒しているならば、そうするためのいくつかの方法があります。他の人が言っているように、遅くて危険な方法はダイナミックを使用することです。

速くて危険な方法は、「例によるキャスト」を使用することです。

static T CastByExample<T>(object obj, T example)
{ 
    return (T)obj; 
}
static void M(object obj)
{
    var anon = CastByExample(obj, new { X = 0 });
    Console.WriteLine(anon.X);  // 123
}
static void N()
{
    M(new { X = 123 });
}

動的タイプをチェックしてプロパティが含まれているかどうかを確認する方法はありますか?

Reflectionを使用します。もちろん、Reflectionを使用する場合は、そもそも動的を使用する必要はありません。ダイナミックを使用してReflectionの使用は避けてくださいなので、とにかくReflectionを使用する場合は、そのまま使用し続けることをお勧めします。

C#では難しいことをしようとしているようです。私はあなたがそれをしたいかどうか、そしてあなたがそうするなら、C#があなたのための言語であるかどうかを再評価します。 IronPythonのような動的言語はあなたのタスクにより適しているかもしれません。

6
Eric Lippert

誰もが「そもそもそれをしないでください」と言いますが、これはまさにasp.mvcが行うことです! (誤解しないでください。私自身は好きではありませんが、カスタムhtmlヘルパーを作成している場合は、通常のhtmlヘルパーと同じように呼び出します...)

また、asp.mvcを使用して、作業を簡単にすることができます。

public void MyMethod(object obj){
  var dic=new System.Web.Routing.RouteValueDictionary(obj);
  string param=dic["myparam"] as string;
}
1
Nadav