2011-08-26 83 views
3

我試圖執行一個擴展方法,返回和T類型的對象,但我想基於一個頭/細節動態泛型類型的T型動態。用動態類型調用通用擴展方法

這也許有點冗長......

using System; 
using System.Collections.Generic; 

namespace Blah 
{ 
    public interface IHeader 
    { 
     string Name { get; set; } 
     IDetail Detail { get; set; } 
    } 

    public interface IDetail 
    { 
     //Nothing the 'Real' implementation of this 
     //interface will have it's own properties. 
    } 

    public class GenericHeader : IHeader 
    { 
     public string Name { get; set; } 
     public IDetail Detail { get; set; } 
    } 

    public class RealHeader : GenericHeader 
    { 
     public new RealDetail Detail 
     { 
      get { return (RealDetail) base.Detail; } 
      set { base.Detail = value; } 
     } 
    } 

    public class RealDetail : IDetail 
    { 
     public string ThisImportantOnlyToRealDetail { get; set; } 
    } 

    public static class ExtensionHelpers 
    { 
     public static T ToObject<T>(this IDictionary<string, string> reader) where T : new() 
     { 
      //This maps the dictionary to Key Value Pairs of the Object's properties 
      //it then will return a object filled with the values 
      return new T(); 
     } 
    } 

    public class MyRepo<THeader> where THeader : class, IHeader, new() 
    { 
     public THeader GetById(int ID) 
     { 
      THeader returnHeader = new THeader(); 
      //Process to fill Header 

      var dictDetail = new Dictionary<string, string>(); 
      //Process to fill Detail Dictionary 

      //Use extension method to create an Object 
      //based on Key Value Pairs from Dictionary 
      // !!!!!!!!!!!!!!!! This Is The Problem !!!!!!!!!!!!!!!! 
      // Can't use typeof for returnHeader.Detail, reflection? 
      returnHeader.Detail = dictDetail.ToObject<typeof(returnHeader.Detail)>(); 

      return returnHeader; 
     } 
    } 

    public class Worker 
    { 
     public void DoWork() 
     { 
      var myRealRepo = new MyRepo<RealHeader>(); 
      var myRealHeader = myRealRepo.GetById(123); 

      Console.WriteLine(myRealHeader.Detail.ThisImportantOnlyToRealDetail); 
     } 
    } 
} 

回答

4

這必須使用反射來完成。

typeof(ExtensionHelpers) 
    .GetMethod("ToObject", BindingFlags.Static | BindingFlags.Public) 
    .MakeGenericMethod(returnHeader.Detail.GetType()) 
    .Invoke(null, new object[] { dictDetail }); 

請注意,由於擴展方法是一種語言功能,因此在使用反射時必須調用方法(如常規靜態方法)。

如果類型始終是動態的,則可能更容易將ToObject更改爲常規非泛型方法,該方法將Type作爲參數。


你的設計是有點問題的實際,你似乎需要知道的實際類型背後的Detail屬性的對象,但是這需要物業已經有一個值,但是你的代碼設置,屬性。

我建議你想想解決這個問題的其他方法。

+0

我有一個小問題,一直試圖去反思,看看我是否可以修復它,但撞到一堵磚牆。 returnHeader.Detail爲null,它無法從中獲取'GetType()'。 –

+0

這就是我提到的你設計的問題。你需要有一種方法來傳達你想要的'Detail'屬性的類型,因爲只要它的值是'null',你知道的唯一類型就是'IDetail',這顯然不能被實例化。也許你可以添加一個'Type DetailType {get; }'屬性到'IHeader'接口,允許實現通知你他們想要使用什麼類型? – Sven

+0

不幸的是,我繼承了這個項目,代碼在其他程序集中使用。我通過在創建回購對象MyRepo 期間傳入類型來修復它,然後我可以將其轉換爲(TDetail)。 –