- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我正在尝试创建一个事先不知道其目标类型的开放委托(delegate)。我不确定这是否解释正确,让我向您展示:
class X
{
public bool test() { return false; }
}
static void Main()
{
var x = new X();
var runtimeType = x.GetType();
var method = runtimeType.GetMethod("test");
var del = ... INSERT CODE
Console.WriteLine(del(x)); // should output False
}
同时 Delegate.CreateDelegate(typeof(Func<X, bool>), method);
有效,但我不知道 X
的类型在编译时。我想做的是使用 typeof(Func<object, bool>)
但这是不可能的。
我搜索并找到了this文章。
我清理了一些代码 - 这是我的相关部分:
public static class MethodInfoExtensions
{
public static Func<TArg0, TReturn> F0<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = (Func<T, TReturn>)Delegate.CreateDelegate(typeof(Func<T, TReturn>), method);
return delegate(TArg0 target) { return d((T)target); };
}
public static T DelegateForCallMethod<T>(this MethodInfo targetMethod)
{
//string creatorName = (targetMethod.ReturnType == typeof(void) ? "A" : "F") + targetMethod.GetParameters().Length.ToString();
// this will just do in my case
string creatorName = "F0";
var methodParams = targetMethod.GetParameters();
var typeGenArgs = typeof(T).GetGenericArguments();
var signature = new Type[1 + methodParams.Length + typeGenArgs.Length];
int idx = 0;
signature[idx++] = targetMethod.DeclaringType;
for (int i = 0; i < methodParams.Length; i++)
signature[idx++] = methodParams[i].ParameterType;
for (int i = 0; i < typeGenArgs.Length; i++)
signature[idx++] = typeGenArgs[i];
var mth = typeof(MethodInfoExtensions).GetMethod(creatorName, BindingFlags.NonPublic | BindingFlags.Static);
var gen = mth.MakeGenericMethod(signature);
var res = gen.Invoke(null, new object[] { targetMethod });
return (T)res;
}
}
现在我可以写了(在插入代码区域)method.DelegateForCallMethod<Func<object, bool>>();
当我调用 del(x)
它会执行 x.test()
并输出 False
正确!
问题是,改变X
成为struct
(这是我的实际用例)打破了它! :(
Unhandled Exception: System.Reflection.TargetInvocationException: Exception has
been thrown by the target of an invocation. ---> System.ArgumentException: Error
binding to target method. at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throw
OnBindFailure) at Vexe.Runtime.Extensions.VexeTypeExtensions.F0[T,TArg0,TReturn](MethodInfo method) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Source\Runtime\RuntimeExtensions\TypeExtensions.cs:line 24
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] argum
ents, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle
typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisib
ilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Vexe.Runtime.Extensions.VexeTypeExtensions.DelegateForCallMethod[T](Method
Info targetMethod) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Source\Runtime\RuntimeExtensions\TypeExtensions.cs:line 50
at Program.Main(String[] args) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Solution\Test\Program2.cs:line 225
(该行是res = ...
)
知道为什么会这样吗?以及如何解决?
谢谢!
编辑:我不想使用 MethodInfo.Invoke。这里的重点是创建一个调用速度比常规反射快得多的委托(delegate)。
编辑: 追查问题,似乎F0
如果 X
则无法创建委托(delegate)是 struct
- 可调用MethodInfoExtensions.F0<X, object, bool>(method);
核实- 如果 X
是一个class
那么没问题!
编辑: 进一步简化,似乎Delegate.CreateDelegate(typeof(Func<X, bool>), method)
如果 X
则无法绑定(bind)是struct
!
编辑找到this - 几乎相同的问题。但是解决方案意味着有一个自定义委托(delegate),其参数类型(在我的例子中是 X)在编译时已知:(
最佳答案
所以问题是Delegate.CreateDelegate(typeof(Func<X, bool>), method)
如果 X
则失败是 struct
- 根据 this我应该创建自己的委托(delegate)并通过 ref。我这样做了,它起作用了,但现在如果我改回 class
就不起作用了!它再次开始为 class
工作但不是 struct
如果我删除 ref
!
给定这个启动代码:
class X
{
public bool test() { return false; }
}
var x = new X();
var runtimeType = x.GetType();
var method = runtimeType.GetMethod("test");
案例 1(如果 X
是类则有效)
delegate TReturn MyDelegate1<TArg0, TReturn>(TArg0 obj);
var del = Delegate.CreateDelegate(typeof(MyDelegate1<X, bool>), method) as MyDelegate1<X, bool>;
Console.WriteLine(del(x));
Case2(如果 X
是结构体则有效)
delegate TReturn MyDelegate2<TArg0, TReturn>(ref TArg0 obj);
var del = Delegate.CreateDelegate(typeof(MyDelegate2<X, bool>), method) as MyDelegate2<X, bool>;
Console.WriteLine(del(ref x));
现在为了用这个来调整原始代码,我必须有两个版本的委托(delegate):一个有 ref,另一个没有。在 DelegateForCallMethod
里面功能,我看看是否 DeclaringType
因为输入方法是一个结构或类,并相应地使用适当的委托(delegate)类型(我什至不确定它是否会起作用)
如果可行,可能会更新以添加代码。
如果有人能解释发生了什么,我们将不胜感激。
编辑:开始吧——(绝对不是最漂亮的——我觉得我在做一些多余的事情):
public delegate TReturn MethodInvoker<TArg0, TReturn>(TArg0 target);
public delegate TReturn MethodInvokerRef<TArg0, TReturn>(ref TArg0 target);
public static MethodInvoker<TArg0, TReturn> F0Class<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = Delegate.CreateDelegate(typeof(MethodInvoker<T, TReturn>), method) as MethodInvoker<T, TReturn>;
return delegate(TArg0 target)
{
return d((T)target);
};
}
public static MethodInvokerRef<TArg0, TReturn> F0Struct<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = Delegate.CreateDelegate(typeof(MethodInvokerRef<T, TReturn>), method) as MethodInvokerRef<T, TReturn>;
return delegate(ref TArg0 target)
{
var typed = (T)target;
return d(ref typed);
};
}
public static Func<TArg0, TReturn> DelegateForCallMethod<TArg0, TReturn>(this MethodInfo targetMethod)
{
var declType = targetMethod.DeclaringType;
var signature = new Type[3]
{
declType,
typeof(TArg0),
typeof(TReturn)
};
bool isValueType = declType.IsValueType;
string delegateCreator;
if (isValueType)
delegateCreator = "F0Struct";
else
delegateCreator = "F0Class";
var mth = typeof(VexeTypeExtensions).GetMethod(delegateCreator, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
var gen = mth.MakeGenericMethod(signature);
var res = gen.Invoke(null, new object[] { targetMethod });
if (isValueType)
{
var mir = (MethodInvokerRef<TArg, TReturn>)res;
return x => mir(ref x);
}
var mi = (MethodInvoker<TArg, TReturn>)res;
return x => mi(x);
}
用法:
var x = // ... usual startup code
var del = method.DelegateForCallMethod<object, bool>();
Console.WriteLine(del(x));
关于c# - 打开目标类型未知的实例委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28268378/
有没有一种方法可以使用标准类型构造函数(例如 int、set、dict、list、tuple 等)以用户定义的方式将用户定义类的实例强制转换为其中一种类型?例如 class Example:
我知道这个问题在Stackoverflow中有很多问题,但是即使有很多答案,这些答案也帮不了我什么,也没有找到答案。 在我的WebAPP中,它可以正常工作,但是当我将其转换为API时,它失败了(主题标
这个问题已经有答案了: Why does the ternary operator unexpectedly cast integers? (3 个回答) 已关闭 9 年前。 最近遇到一个Java的陷
我尝试使用 FirebaseApp.configure() 配置 Firebase,但遇到以下崩溃: *** Terminating app due to uncaught exception 'c
我有一个自连接员工实体类,其中包含与其自身相关的 id、name 和 ref 列。我想创建它的新实例并将其保存到数据库。 首先我创建了一个 Employee 类的实例并将其命名为 manager。然后
我有一个用于添加新公寓的表单,在该表单中我有一个下拉列表,用户可以在其中选择负责的人员。 显然,当您从下拉列表中选择并尝试保存公寓时,我的应用程序认为该人已被修改。它给了我下面的错误,指示我应该首先保
从 Visualforce 页面,我需要检索我们组织的 salesforce 实例的 URL,而不是 Visual Force URL。 例如我需要https://cs1.salesforce.com
我遇到了一些可能的问题答案,但这是关于从 Hibernate 3.4.0GA 升级到 Hibernate 4.1.8 的问题。所以这曾经在以前的版本下工作,我已经四处搜索了为什么它在这个新版本中出现了
似乎一遍又一遍地问这个问题,我仍然找不到解决我问题的答案。我在下面有一个域模型。每个新创建或更新的“安全用户”都需要我确保其具有配置文件,如果没有,则创建一个新的配置文件并分配给它。 配置文件的要求相
我很难调试为什么 JPA 不级联我的 @ManyToMany 关系。我发现的所有答案都与缺少级联语句有关。但我确实拥有它们并且仍然得到: Caused by: org.hibernate.Transi
Play 服务 API 表明有一个叫做 Instance ID 的东西 但是,在 Android Studio 中包含以下内容后,我无法导入 InstanceID 类 compile "com.goo
我正在使用 Seam 框架。我有 2 个实体: 请求.java @Entity @Table(name = "SRV_REQUEST") public class Request { private
This question处理构建一个适当的Monad来自单子(monad)的实例,但仅在某些约束下 - 例如Set .诀窍是将其包装成 ContT ,它将约束推迟到包装/展开其值。 现在我想对 Ap
我正在尝试执行此查询: StringBuffer sb = new StringBuffer(); sb.append("select p from PointsEntity p " + "where
我试图了解是否可以更改我的 hibernate 配置并使用单个 MySQL 实例(而不是我当前拥有的多个 MySQL 实例): 我有一个使用 hibernate 的 Java 应用程序,与 2 个模式
我有一个选项卡滑动布局,其中包括四个选项卡,每个选项卡都有自己的布局和 fragment ,在我的主要 Activity 布局中,viewpager 参与更改选项卡。特定 View (选项卡)在应用程
我看到很多帖子声称他们正在运行 MySql 的 RDS 实例,但无法连接到该实例,但我没有运行 RDS。 我使用 EC2 实例来托管我的 WordPress 博客,该博客是使用 Web 平台安装程序安
因为我在我的 ec-2 实例上的 python 虚拟环境中运行应用程序( Airflow ),并且我想在同一个 ec2 实例上的默认 python 环境中运行命令,所以我认为 ssh 到我自己的实例更
这个问题已经有答案了: How to fix the Hibernate "object references an unsaved transient instance - save the tra
例子: run APP1 .. ... run APP1 ... run APP2 如何在 APP2 中对 Vue 说我需要调用 APP1?
我是一名优秀的程序员,十分优秀!