我有以下方法签名:
public static void InvokeInFuture(Delegate method, params object[] args)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
委托和参数将保存到集合中以供将来调用.
有没有办法可以检查arguments数组是否满足委托要求而不调用它?
谢谢.
编辑: 感谢您的反思实现,但我正在寻找一种内置的方法来实现这一点.我不想重新转换方向盘,.NET Framework已经在Delegate.DynamicInvoke()的某个地方实现了这种检查,实现处理所有那些只有微软开发人员可以考虑的疯狂特殊情况,并通过了单元测试和QA.有没有办法使用这个内置实现?
谢谢.
我一直在用__invoke魔术方法做一些测试(替换旧代码),我不确定这是不是一个bug:
让我们假设我们有一个班级:
class Calc {
function __invoke($a,$b){
return $a*$b;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是可能的,并且没有任何问题:
$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20
Run Code Online (Sandbox Code Playgroud)
但是,如果我想要另一个类来存储该对象的实例,这不起作用:
class Test {
public $k;
function __construct() {
$c = new Calc;
$this->k = $c; //Just to show a similar situation than before
// $this-k = new Calc; produces the same error.
}
}
Run Code Online (Sandbox Code Playgroud)
当我们尝试调用它时会发生错误:
$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()
Run Code Online (Sandbox Code Playgroud)
我知道"解决方案"可能是在类Test(名为k)中使用call_user_func_array来"转发"调用,但这并不优雅.
我需要将该实例保留在公共类中(出于设计目的)并能够将其作为函数从其他类中调用...任何建议?
更新:
我找到了一些有趣的东西(至少对我而言):
如果我们将"类变量"分配给局部变量,它可以工作:
$t = new Test; …Run Code Online (Sandbox Code Playgroud) 我正在ASP.NET中创建一个较小的RPG游戏.在这个游戏中,我有一个项目架构,每个项目都有一些方法.例如,所有项目应共享" 丢弃 "," 检查 "和" 使用 "等方法.有些项目必须使用" 操作 "," 计算 "等方法进行扩展.
到目前为止,我已经创建了以下对象GameActionList:
public delegate void MyDelegate();
public class GameActionList
{
public List<MyDelegate> Items = new List<MyDelegate>();
public void Add(MyDelegate del)
{
Items.Add(del);
}
public void CallDelegates()
{
foreach (MyDelegate myDelegate in Items)
{
myDelegate();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个BaseItem类,它有这个GameActionList.BaseItem类中的get属性是这样的:
public GameActionList Actions
{
get
{
GameActionList actions = new GameActionList();
actions.Add(this.Drop);
actions.Add(this.Examine);
return actions;
}
}
Run Code Online (Sandbox Code Playgroud)
这很好,但是......我有一些问题!
我的问题
我需要一种更通用的GameActionList方式.我需要有一个列表,不仅有空洞,还有函数.另外,我需要两个带参数和无参数的方法.
例如:Drop方法需要一个Player对象,因此他可以删除该项.该检查方法需要返回一个字符串descriping的项目.
另外,我需要一些我在初始化GameActionList时不知道的数据:我在调用方法时首先知道这些数据...
所以我有两个问题:
另外......这可能是一个非常愚蠢的方法,所以如果你有一些更优雅的解决方案..我已经准备好听了!
非常感谢...!拉尔斯
我最近更改了我的应用程序,使用自定义SplashScreen(它只是一个带有Timer的表单,主窗体并自行关闭)到应用程序框架.
这是我做的:
这完全符合我的要求.SplashScreen首先显示,而不是启动事件触发并且它是否正常工作.SplashScreen关闭,显示实际的主窗体.
到现在为止还挺好.但我们的客户有时会在启动期间遇到这个令人讨厌的异常:
System.InvalidOperationException: Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.
bei System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle)
bei System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
bei System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
bei System.Windows.Forms.Control.Invoke(Delegate method)
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen()
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object sender, EventArgs e)
bei System.EventHandler.Invoke(Object sender, EventArgs e)
bei System.Windows.Forms.Form.OnLoad(EventArgs e)
bei System.Windows.Forms.Form.OnCreateControl()
bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
bei System.Windows.Forms.Control.CreateControl()
bei System.Windows.Forms.Control.WmShowWindow(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
bei …Run Code Online (Sandbox Code Playgroud) 我有一点问题.我正在开发一个Android applikation.在那里,您可以动态地从其他应用程序(包)加载类.首先,我不想"破解"第三方应用程序,我想尝试为自己的应用程序构建插件.那我有什么?
2测试应用程序和包含两个应用程序的1个库.
所以app1的代码:
package com.ftpsynctest.app1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import android.app.Activity;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import com.syncoorp.ftpsyncx.commons.SyncFile;
import dalvik.system.PathClassLoader;
public class App1Activity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SyncFile f = new SyncFile("bla");
String classname = "com.ftpsynctest.app2.classcall";
String classpath = getApk("com.ftpsynctest.app1") + ":" + getApk("com.ftpsynctest.app2");
PathClassLoader myClassLoader = new dalvik.system.PathClassLoader(classpath, ClassLoader.getSystemClassLoader());
try {
Class c = Class.forName(classname, true, myClassLoader);
for (Method m : c.getDeclaredMethods()) {
System.out.println("Method: " + m.getName());
for (Type t …Run Code Online (Sandbox Code Playgroud) 我正在尝试构建一个使用System.ComponentModel.ISynchronizeInvoke的对象,该对象具有以下方法:(其中包括)
public object Invoke(Delegate method, object[] args)
Run Code Online (Sandbox Code Playgroud)
使用给定参数调用方法的最佳方法是什么?我可以用:
public object Invoke(Delegate method, object[] args)
{
return method.DynamicInvoke(args);
}
Run Code Online (Sandbox Code Playgroud)
但这是后期限制.我的直觉是,这是调用方法的唯一方法..任何想法?
我正在尝试动态加载一些.dll文件.文件是插件(现在自编),至少有一个实现的类MyInterface.对于每个文件,我正在执行以下操作:
Dictionary<MyInterface, bool> _myList;
// ...code
Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
foreach (Type type in assembly.GetTypes())
{
var myI = type.GetInterface("MyInterface");
if(myI != null)
{
if ((myI.Name == "MyInterface") && !type.IsAbstract)
{
var p = Activator.CreateInstance(type);
_myList.Add((MyInterface)p, true);
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行此操作会导致强制转换异常,但我找不到解决方法.无论如何,我想知道为什么这根本不起作用.我正在寻找.NET Framework 3.5中的解决方案.
发生在我身上的另一件事是null在上面的代码中p添加新条目之前运行以下内容后进入_myList:
var p = type.InvokeMember(null, BindingFlags.CreateInstance, null,
null, null) as MyInterface;
Run Code Online (Sandbox Code Playgroud)
此代码是在加载插件的第一次尝试,我也没找出原因p是null还没有.我希望有人能以正确的方式引导我:)
基本上我试图通过名称调用dll,实例化一个对象,然后在该dll中按名称调用方法.我得到了一个"调用目标引发了异常." 在Method.Invoke期间.我很确定我的问题是对方法的参数进行类型转换.我想知道是否有人对此异常有任何意见.此外,欢迎任何有关如何修改我的方法的建议.
public void calldll(string dllName, string typeName, string methodName, string arguments) {
string[] argumentArray = arguments.Split(new char[] { '|' }, StringSplitOptions.None);
Assembly assembly = Assembly.LoadFrom(dllName);
System.Type type = assembly.GetType(typeName);
Object o = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod(methodName);
ParameterInfo[] parameters = method.GetParameters();
object[] methodParameters = new object[parameters.GetLength(0)];
for (int i = 0; i < parameters.Length - 1; i++)
{
var converter = TypeDescriptor.GetConverter(parameters[i].GetType());
methodParameters[i] = converter.ConvertFrom(argumentArray[i]);
}
method.Invoke(o, methodParameters); }
Run Code Online (Sandbox Code Playgroud) 我是线程世界的新手,但我正在研究的应用程序的一些方面要求我使用BackgroundWorker控件来防止UI在执行某些文件操作时冻结.
我要做的是从BackgroundWorker中更新几个表单标签.从来没有使用过这个之前我很快发现我无法访问未在同一个线程中创建的控件,因此经过一些研究后我实现了以下代码,似乎可以使一切工作:
Private Delegate Sub DelegateUpdateStatus(ByVal statusText As String, ByRef currentFile As String)
Private Sub UpdateStatus(ByVal statusText As String, ByVal currentFile As String)
If InvokeRequired Then
Invoke(Sub() LblStatus.Text = statusText)
Invoke(Sub() LblCurrentFile.Text = currentFile)
Else
LblStatus.Text = statusText
LblCurrentFile.Text = currentFile
End If
End Sub
Run Code Online (Sandbox Code Playgroud)
但事情是,我不知道这个代码在做什么,或者为什么需要它.
我做了一些研究,但我没有做过任何真正的工作,我读过的大多数文章都假设了一些先验知识.
我希望了解的三个主要内容:
如上所述,线程仍然是一个非常外国的概念,所以任何简单的英语答案都会非常有用 - 谢谢!
编辑:感谢大家到目前为止的回复.我已经做了一些进一步的阅读,我想知道我是否正确地采用了这种方式.我使用BackgroundWorker的原因是为了确保在我执行文件操作时UI保持响应.问题是,我仍然需要等到BackgroundWorker完成它的工作,所以我可以返回一个指示操作成功的布尔值.有办法解决这个问题,但是从我的阅读中,不得不等待BackgroundWorker完成它的工作就是首先要破坏使用它的目的.那么,阻止UI锁定的最佳方法是什么?
我有一个由第三方提供的.Net库.我对其中一个类进行了反射,并找到了一个成员方法.签名是......
Byte& FooBar()
Run Code Online (Sandbox Code Playgroud)
所以,我想通过反射调用这个方法并获得异常"反射调用中不支持ByRef返回值".
这是我试过的......
var strm = new TheirClass();
var t = strm.GetType();
var ms = t.GetMembers(
BindingFlags.Static|BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var m in ms)
{
Debug.WriteLine(String.Format("Name: {0}: {1}", m.Name, m.ToString()));
// ...
// Name: FooBar: Byte& FooBar()
// ...
}
var meth = t.GetMethod("FooBar");
object returnValue = meth.Invoke(strm, new object[] { }); //throw exception
Run Code Online (Sandbox Code Playgroud)
我已经尝试提供参数,如使用ref参数调用函数,但这没有任何区别.
我想在C#中解决这个异常.