2011-08-26 62 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)。 –