Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用反射创建通用对象_C#_Generics_Reflection_.net 4.5 - Fatal编程技术网

C# 如何使用反射创建通用对象

C# 如何使用反射创建通用对象,c#,generics,reflection,.net-4.5,C#,Generics,Reflection,.net 4.5,首先让我说,我想做的是获取泛型类中属性的值,该值可能被从泛型类继承的类重写。在基类中将其视为默认值,该类的继承者可以重写它来设置自己的默认值 我曾尝试使用System.reflection.FieldInfo.GetValue直接在类型上使用反射,但这不适用于具有泛型类型的类。所以我认为我需要实例化这个类,以便能够看到值是什么 通过读取bin中的DLL并使用反射查找从接口继承的类型,我检索到了“类型” 我正在使用.NET4.5 这里的文档似乎准确地解释了我需要做什么 在本文档中,我能看到的唯一

首先让我说,我想做的是获取泛型类中属性的值,该值可能被从泛型类继承的类重写。在基类中将其视为默认值,该类的继承者可以重写它来设置自己的默认值

我曾尝试使用System.reflection.FieldInfo.GetValue直接在类型上使用反射,但这不适用于具有泛型类型的类。所以我认为我需要实例化这个类,以便能够看到值是什么

通过读取bin中的DLL并使用反射查找从接口继承的类型,我检索到了“类型”

我正在使用.NET4.5

这里的文档似乎准确地解释了我需要做什么

在本文档中,我能看到的唯一区别是我们是如何获得类型的,我在bin中查找类型,它们只是简单地称为typeof(),因为类型非常复杂,似乎这可能是不匹配的,但我看不到缺少什么(如果有)

foreach(类型中的变量项)
{
var ts=item.GetField(“DefaultTimeToExpire”);
Type[]typeArguments=item.GetGenericArguments();
如果(ts!=null)
{
var t=item.MakeGenericType(类型参数);
var obj=Activator.CreateInstance(t);
var timespan=obj.DefaultTimeToExpire;
添加(新元组(item.Name、item、timespan));
}
}
我调用GetField来查找具有字段“DefaultTimeToExpire”的项。到目前为止,这部分功能可以很好地找到我需要的类型。 接下来我调用GetGenericArguments,它返回一个预期的类型参数数组。 然后我调用MakeGenericType 最后,Create instance给出了错误消息

“无法创建BusinessLogic.TestSubscriberXXX`1[Message]的实例,因为Type.ContainsGenericParameters为true。”

这看起来正是我应该做的。
谢谢

为了实例化泛型类型,您需要知道应该替换其类型参数的实际值(类型)。
GetGenericArguments()
方法是一种反射形式,它只提供类型参数,而不是它们的实际值。价值观取决于你。。。这就是泛型的全部要点

如果
item
是类似
List
的类型,则
item.GetGenericArguments()
将返回一个数组,其中包含一个假“type”,表示类型参数
T
(其
IsGenericParameter
属性设置为true)。因此,将该参数类型传递回
item.MakeGenericType()
将创建另一个与原始类型等效的打开泛型类型。要关闭泛型类型以便对其进行实例化,您需要提供一个实际的(非参数)类型参数,例如
int

例如,
typeof(List).MakeGenericType(typeof(int))
将返回
typeof(List)
,而
typeof(List).MakeGenericType(typeof(List).GetGenericArguments())
将再次返回
typeof(List)
。这就是代码中正在发生的事情


很抱歉,如果这有点模糊,我不知道如何解释它。底线是像
列表
这样的类型只有在您有一个类型要替代
T

时才有用。您的
类型参数
中是否可能没有足够的类型来设置泛型的所有类型参数?奇怪的错误,很难猜测您最终是如何得到一个开放类型的。快捷方式是只使用Activator.CreateInstance(item.GetType())。当我调用GetGenericArguments()并检查返回的内容时,item是一个类似于列表的类型,它返回我期望的类型。“用户”。值得怀疑的一件事是FullName为null,尽管它确实具有程序集完全限定名FullName为null是奇怪的。。。我以前从未见过这种情况。如果它返回的是用户(并且用户是实际类型,而不是类型参数),那么您已经有了一个封闭的泛型类型。然后,您应该能够简单地执行
Activator.CreateInstance(item)
”。好的,我不知道为什么我不能创建正确的泛型类型以允许CreateInstance工作,但我已经解决了我的问题。这段代码实际上在一个泛型类中,该类实现了我试图创建为泛型类型的类型。所以我可以写:`var typeArg=typeof(T);var t=item.MakeGenericType(typeArg);ISubscriber subscriber=(ISubscriber)Activator.CreateInstance(t);var timespan=subscriber.DefaultTimeToExpire;添加(新元组(item.Name、item、timespan))`
foreach (var item in types)
{
    var ts = item.GetField("DefaultTimeToExpire");
    Type[] typeArguments = item.GetGenericArguments();
    if (ts != null)
    {
        var t = item.MakeGenericType(typeArguments);
        var obj = Activator.CreateInstance(t);
        var timespan = obj.DefaultTimeToExpire;
        subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan));
    }
}