2016-03-29 16 views
0

を経由して、一般的な性質の取り扱い:は反射

public class Wrapper<T> 
{ 
    public T Data { get; set; } 
    public string[] Metadata { get;set; 
} 

と別のクラスは、ジェネリックずにその値を公開します。

public class SomeOtherClass 
{ 
    public object WrappedData { get;set }; 
} 

、私は元開封されたデータを取得する方法?

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>)) 
{ 
    dynamic originalValue = someOtherClass.WrappedData; 
} 

を、私はその後、RuntimeBinderExceptionを取得し、originalValue.Dataプロパティを呼び出すことはできません。

私は次のようなものを使用して、それをテストすることができます。


もう少し文脈を助けるかもしれない

更新。私はHATEOASを実装したいWebAPIに取り組んでいます。だから、私のラッパークラスには、返されるデータとメタデータが含まれています。データをアンラップし、レスポンスボディーに戻し、応答ヘッダーにメタデータを入れるアクションフィルターを作成しています。次のようにアクションフィルタは現在実装されています

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    if (actionExecutedContext.Request.Method == HttpMethod.Get) 
    { 
     var objectContent = actionExecutedContext.Response.Content as ObjectContent; 
     if (objectContent != null) 
     { 
     var type = objectContent.ObjectType; 
     var formatter = actionExecutedContext 
      .ActionContext 
      .ControllerContext 
      .Configuration 
      .Formatters 
      .First(f => f.SupportedMediaTypes 
       .Contains(new MediaTypeHeaderValue(actionExecutedContext 
        .Response 
        .Content 
        .Headers 
        .ContentType 
        .MediaType))); 

      if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>)) 
      { 
       dynamic value = objectContent.Value; 
       actionExecutedContext.Response.Content = new ObjectContent(value.Data.GetType(), value.Data, formatter); 
      } 
     } 
    } 

    base.OnActionExecuted(actionExecutedContext); 
} 

を明らかに私のすべてのAPIエンドポイントは、現在、そのデータをラップではないので、応答がWrapper<T>インスタンスを返すされていない場合、私は応答を変更することなく、アクションフィルタを終了します。そうである場合は、.Dataの値を取り出し、応答本体を書き換えます。

+0

'何が含まれてWrapperData'んを行うことができますか?'Wrapper .Data'の値しか含まれていなければ、それは明らかです。ラッパー全体が含まれている場合は、初期化側で問題を探す必要があります。 –

+0

'type'変数は何を含んでいますか? –

答えて

1

それは何objectContent.ObjectTypeで掲示コードから明らかではないので、私は実際の値をチェックするコードを変更します:

object value = objectContent.Value; 
if (value != null && value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition() == typeof(Wrapper<>)) 
{ 
    object data = ((dynamic)value).Data; 
    actionExecutedContext.Response.Content = new ObjectContent(data.GetType(), data, formatter); 
} 

をしかし、あなたは反射と動的呼び出しを避けるために、あなたならば、あなたの人生ははるかに簡単に行うことができますジェネリッククラスをジェネリックでないインターフェースでバックアップしてください。インスタンス

public interface IWrapper 
{ 
    object Data { get; } 
    string[] Metadata { get; } 
} 

public class Wrapper<T> : IWrapper 
{ 
    public T Data { get; set; } 
    object IWrapper.Data { get { return Data; } } 
    public string[] Metadata { get; set; } 
} 

について次に簡単な

var wrapper = objectContent.Value as IWrapper; 
if (wrapper != null) 
{ 
    actionExecutedContext.Response.Content = new ObjectContent(wrapper.Data.GetType(), wrapper.Data, formatter); 
} 
+0

SImpleは最高です:-) –

0

タイプをラッパーに追加した場合は役に立ちますか?

あなたがやろうとしている正確に何
public class Wrapper<T> 
{ 
    public Type MyType{get;set;} 
    public T Data { get; set; } 
    public string[] Metadata { get;set;} 

    public Wrapper(T data){ 
     MyType = data.GetType(); 
     Data = data; 
    } 
} 
+0

どうすればMyTypeプロパティを取得できますか? Dataプロパティと同じようにアクセスするのは難しいことです。 SomeOtherClass.WrappedDataのインスタンスをWrapper にインスタンス化またはキャストするにはどうすればよいですか? –

+0

ええ、それは良い質問です。申し訳ありませんが、私は元の投稿を少し間違って読みました。あなたはなぜこのトリックbtwを行う必要があるのか​​尋ねるのが理にかなっていますか?これらのソリッドデザインのボクシングの価値にはちょっと奇妙な気がします。私は興味があります。あなたはおそらくそうするための完全な理由があります。 –

+0

私は質問をいくつかの文脈で更新しました。 –

0

不明:Dataプロパティ内のWrappedDataプロパティがあるという保証がないこと

object obj = new Wrapper<SomeOtherClass> { Data = new SomeOtherClass { WrappedData = "Hello" } }; 
Type type = obj.GetType(); 

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>)) 
{ 
    dynamic data = ((dynamic)obj).Data; 
    dynamic wrappedData = data.WrappedData; 
} 

注:WrappedDataSomeOtherClassの財産ですが、例えばobjは次のようになります。

object obj = new Wrapper<string> { Data = "Hello" }; 
1

次のコードは動作します:

using System; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 

     public class Wrapper<T> 
     { 
      public T Data { get; set; } 
      public string[] Metadata 
      { 
       get; set; 
      } 

     } 

     public class SomeOtherClass 
     { 
      public object WrappedData { get; set; } 
     } 


     static void Main(string[] args) 
     { 
      var wrappedData = new Wrapper<int> { Data = 3 }; 
      var someObject = new SomeOtherClass { WrappedData = wrappedData }; 

      dynamic d = someObject.WrappedData; 
      Console.WriteLine(d.Data); 

     } 
    } 
} 

だから、あなたの問題点は明確ではありません。