c# - 如何调用具有结构约束的方法到未知结构

标签 c# .net reflection struct

问题很简单:我正在使用反射来获取值。然后,如果它是一个 struct,我将调用一个方法 FooStruct,否则 FooClass:

Type type = x.GetType();
foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
    var val = fieldInfo.GetValue(value);
    object obj = type.IsValueType ? val.FooStruct() : val.FooClass();
    fieldInfo.SetValue(x, obj);
}

问题是 FooStruct 有一个约束:

public static T FooStruct<T>(this T value) where T : struct
{
    //...
}

所以问题是:是否可以为包含装箱结构实例而不进行反射的对象调用具有 struct 约束的方法?

最佳答案

我很乐意被另一个答案证明是错误的,但我认为如果不更多地进行反射(reflection),这是不可能的。请参阅下文进一步了解让我怀疑这一点的原因。有关基于反射的解决方案,请参阅答案的结尾。

实用建议:我会简单地放弃对你的 FooStruct 的约束和 FooClass方法,另外:

  • 要么让它们成为非通用的,要么接受类型为 object 的参数(这就是 val 被声明为,无论如何)。如果这些方法只被传递,那么让这些方法成为通用的就没有任何优势 object ;

  • 或投 val来自 objectT在调用之前 FooStruct/FooClass .

为什么似乎无法完成您的要求?您正在尝试转换静态类型的表达式 object (即 val )到静态类型的东西 <T> where T : struct<T> where T : class (为了在这样的 T 上调用相应的扩展方法)。也就是说,您正试图在 foreach 中动态引入一个新的类型变量。环形。不幸的是,引入类型变量的唯一方法是提前声明它,即作为一些泛型类型参数 T在方法的签名中;然后,不是您的方法内部的代码可以选择它代表的实际类型——是调用的代码决定T .

基于反射的解决方案:

// determine which method ought to be called based on `val`'s run-time type.
// (for C# 6 and later, use the `nameof` operator instead of hard-coding method names)
Type type = val.GetType();
string fooName = type.IsValueType ? "FooStruct" : "FooClass";

// bind to the generic method and supply the type argument for it:
// (I'm assuming that your extension methods are defined in `FooMethodsClass`.)
MethodInfo fooOpen = typeof(FooMethodsClass).GetMethod(fooName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo foo = fooOpen.MakeGenericMethod(new Type[] { type });

// invoke the generic (extension) method with `val` as the `this` argument:
foo.Invoke(null, new object[] { val });

关于c# - 如何调用具有结构约束的方法到未知结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27965803/

相关文章:

c# - 可空日期异常处理-有没有更好的方法

c# - Xamarin.iOS 和 Xamarin.Android 的 NuGet 包缩写是什么?

c# - 线程只阻塞第一个线程(尝试二)

c# - 仅在 C# 中的特定时间触发事件

.net - 显示不正确的密码信息

c# - Java .NET 互操作

C# 反射获取嵌套属性类型中 GetValues 的对象

c# - 如何在 C# 中动态加载 VB 6.0 dll?

scala - Akka - 使用反射创建 Actor

C#如何解决循环对象引用