C# 使用动态类型调用泛型扩展方法

C# 使用动态类型调用泛型扩展方法,c#,generics,types,extension-methods,dynamic,C#,Generics,Types,Extension Methods,Dynamic,我正在尝试执行一个扩展方法,该方法返回类型为T的and对象,但我正在尝试使类型为T dynamic基于Header/Detail动态泛型类型 这可能有点冗长 using System; using System.Collections.Generic; namespace Blah { public interface IHeader { string Name { get; set; } IDetail Detail { get; set; }

我正在尝试执行一个扩展方法,该方法返回类型为T的and对象,但我正在尝试使类型为T dynamic基于Header/Detail动态泛型类型

这可能有点冗长

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);
        }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间废话
{
公共接口IHeader
{
字符串名称{get;set;}
IDetail详细信息{get;set;}
}
公共接口IDetail
{
//这一“真正”的实现毫无意义
//接口将具有自己的属性。
}
公共类GenericHeader:IHeader
{
公共字符串名称{get;set;}
公共IDetail详细信息{get;set;}
}
公共类RealHeader:GenericHeader
{
公共新RealDetail详细信息
{
获取{return(realdeail)base.Detail;}
set{base.Detail=value;}
}
}
公共类realdeail:IDetail
{
公共字符串thismortionallytorealdetail{get;set;}
}
公共静态类扩展助手
{
公共静态T对象(此IDictionary读取器),其中T:new()
{
//这会将字典映射到对象属性的键值对
//然后它将返回一个填充了值的对象
返回新的T();
}
}
公共类MyRepo,其中的排序:类,IHeader,new()
{
公共THeader GetById(内部ID)
{
THeader returnHeader=新THeader();
//填充标题的过程
var dictDetail=新字典();
//填写详细信息字典的过程
//使用扩展方法创建对象
//基于字典中的键值对
//这就是问题所在!!!!!!!!!!!!!!!!
//无法对returnHeader使用typeof。详细信息,反射?
returnHeader.Detail=dictDetail.ToObject();
返回头;
}
}
公社工人
{
公共工作
{
var myRealRepo=新MyRepo();
var myRealHeader=myRealRepo.GetById(123);
Console.WriteLine(myRealHeader.Detail.thismortionallytorealdetail);
}
}
}

这必须使用反射来完成

typeof(ExtensionHelpers)
    .GetMethod("ToObject", BindingFlags.Static | BindingFlags.Public)
    .MakeGenericMethod(returnHeader.Detail.GetType())
    .Invoke(null, new object[] { dictDetail });
请注意,由于扩展方法是一种语言特性,因此在使用反射时必须像调用常规静态方法一样调用该方法

typeof(ExtensionHelpers)
    .GetMethod("ToObject", BindingFlags.Static | BindingFlags.Public)
    .MakeGenericMethod(returnHeader.Detail.GetType())
    .Invoke(null, new object[] { dictDetail });
如果类型始终是动态的,那么将
对象
更改为以
类型
为参数的常规非泛型方法可能更容易


实际上,您的设计有点问题,因为您似乎需要知道
Detail
属性背后的对象的实际类型,但这要求该属性已经有一个值,而您的代码正在设置该属性


我建议您考虑其他方法来处理此问题。

我遇到了一个小问题,一直试图检查反射,看看是否可以修复它,但遇到了麻烦。returnHeader.Detail为null,无法从中获取“GetType()”。这就是我提到的设计中的问题。您需要有一种方法来传递希望
Detail
属性成为的类型,因为只要它的值是
null
,您所知道的唯一类型就是
IDetail
,它显然无法实例化。也许您可以将
Type DetailType{get;}
属性添加到
IHeader
接口中,该接口允许实现通知您它们要使用的类型?不幸的是,我继承了此项目,并且代码在其他程序集中使用。我通过在创建repo对象MyRepo时传入类型来修复它,然后我可以将它转换为(TDetail)。