Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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#_.net_Generics_Reflection - Fatal编程技术网

C#:如果匹配不明确,如何在具有反射的泛型类中获得正确的方法?

C#:如果匹配不明确,如何在具有反射的泛型类中获得正确的方法?,c#,.net,generics,reflection,C#,.net,Generics,Reflection,我有以下方法: object Create(Type type) { var constructor = type.GetConstructor(typeof(int)); return constructor?.Invoke(new object[] {42}); } 此方法适用于大多数类型,要么查找并调用构造函数,要么返回null。但是,当传递以下类型时,它抛出System.Reflection.AmbiguousMatchException: class C<T&g

我有以下方法:

object Create(Type type)
{
    var constructor = type.GetConstructor(typeof(int));
    return constructor?.Invoke(new object[] {42});
}
此方法适用于大多数类型,要么查找并调用构造函数,要么返回null。但是,当传递以下类型时,它抛出
System.Reflection.AmbiguousMatchException

class C<T>
{
    public C(int v) { Console.WriteLine("int"); }
    public C(T v) { Console.WriteLine("T"); }
}

Create(typeof(C<int>));
C类
{
公共C(int v){Console.WriteLine(“int”);}
公共C(tv){Console.WriteLine(“T”);}
}
创建(类型(C));
这是意料之中的,因为有两个构造函数具有相同的签名,但问题是:如何调用特定的构造函数(在本例中,是将打印
“int”
)的构造函数?如果我使用
GetConstructors()
并枚举它们,就会得到两个完全相同的构造函数。似乎
ConstructorInfo
ParameterInfo
API没有提供任何信息来区分它们:它们都是非泛型方法,并且它们的参数类型都是
Int32


同样的问题也适用于遵循相同模式的构造函数以外的方法。

消除构造函数歧义的一种可能方法是查看构造函数信息的属性:

// Get the ConstructorInfo for C<T>.C(int):
var c1 = typeof(C<>).GetConstructor(new[] { typeof(int) });

// Get the matching ConstructorInfo for C<int>.C(int):
var c2 = typeof(C<int>).GetConstructors().Single(c => c.MetadataToken == c1.MetadataToken);

c2.Invoke(new object[] { 42 }); // Outputs "int"
//获取C.C(int)的构造函数信息:
var c1=typeof(C).GetConstructor(new[]{typeof(int)});
//获取C.C(int)的匹配构造函数信息:
var c2=typeof(C).GetConstructors().Single(C=>C.MetadataToken==c1.MetadataToken);
c2.调用(新对象[]{42});//输出“int”

我之所以说“潜在”是因为,尽管我在使用.NET Core 2.0和.NET Framework 4.7测试代码时在我的机器上获得了所需的输出,但我对.NET内部结构还不够熟悉,无法理解这种方法是否保证有效。

为什么要在一般场景中使用反射?泛型的存在使您不必求助于破坏编译时类型安全性的混乱的东西,如动态、对象或反射。@Christopher my Create方法与泛型无关,总是希望调用具有特定签名的构造函数(即类型协定)。我只是想让它继续按预期工作,以防有人传递我所描述的类型。泛型可以用来创建实例,但有一个简单的约束:|但是,如果你有一个创建函数听起来像工厂模式。好吧,技术上的反射是正确的。反思是一种模糊。你必须明确你想要哪一个。这似乎是一个很好的短期解决方案。从长远来看,我决定更改合同,改为要求使用静态工厂方法(不尝试解决歧义),这样API的使用者就可以在不违反合同的情况下拥有任意多的构造函数(因为可能会有来自多个通用参数的相同构造函数,但这两个参数都不可取)。