在C#中的函数指针 [英] Function pointers in C#

查看:152
本文介绍了在C#中的函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在某些方面(或两者)代表的MethodInfo 资格获得这个称号。然而,无论是提供一个我在寻找句法的文雅。因此,简而言之,有没有一些办法,我可以写:

  FunctionPointer富= //什么的,创建函数使用机制
富()指针;



我不能使用固体委托(即使用代表关键字来声明委托类型),因为没有办法知道,直到运行时的具体参数列表方式。作为参考,这是我一直在LINQPad目前玩弄,其中 B 将(大部分)用户生成的代码,等会,从而为准确,以我的用户,我想删除 .CALL

 无效的主要()
{
一个富=新的b();
富[SomeFuntion]()调用。
}

//定义其它的方法和类在这里
接口■功能{
void调用();
void调用(params对象[]参数);
}

类A {
私有类功能:■功能{
私人MethodInfo的_mi;
非公开A _this;
公共功能(A @this,MethodInfo的MI){
_mi = MI;
_this = @this;
}

公共无效调用(){调用(NULL); }
公共无效呼叫(params对象[]参数){
_mi.Invoke(_this,参数);
}
}

&字典LT;字符串,MethodInfo的>功能=新词典<字符串,MethodInfo的>();

公开发行A(){​​
名单,LT; MethodInfo的>毫升=新的List< MethodInfo的>(this.GetType()的getMethods());
的foreach(MethodInfo的MI中的typeof(对象).GetMethods())
{
的for(int i = 0; I< ml.Count;我++)
{
如果(毫升[I] .Name点== mi.Name)
ml.RemoveAt(ⅰ);
}
}

的foreach(MethodInfo的MI在毫升)
{
功能[mi.Name] = MI;
}
}

公共■功能此[字符串函数] {
获得{
如果(!functions.ContainsKey(功能))
抛出新的ArgumentException();

返回新的功能(这一点,函数[功能]);
}
}
}

密封B类:A {
公共无效SomeFuntion(){
Console.WriteLine(SomeFunction称为。);
}
}


解决方案

您说你想保留的数量和参数类型开放的,但你可以做到这一点与一个delgate:

 公共委托对象DynamicFunc (params对象[]参数); 

这正是你现在有同样的事情。试试这个:

 类节目
{
静态无效的主要(字串[] args)
{
DynamicFunc F =票面=>
{
的foreach(在参数变种P)
Console.WriteLine(P);

返回NULL;
};

F(1,4,你好);
}
}

您可以非常想到一个实例方法委托类似于您功能类:一个对象的一个​​的MethodInfo 。所以没有必要把它改写



也能起到C和C指针++都没有任何接近你所需要的:他们不能被绑定到一个对象实例的的功能,此外,他们都是静态类型,而不是动态类型。



如果你想包装在DynamicFunc委托任何其他方法,试试这个

 公共静态DynamicFunc MakeDynamicFunc(对象的目标,MethodInfo的方法)
{
返回面值=> method.Invoke(目标,标准杆);
}

公共静态无效美孚(字符串s,诠释N)
{
Console.WriteLine(S);
Console.WriteLine(N);
}

和则:

  DynamicFunc F2 = MakeDynamicFunc(空的typeof(程序).GetMethod(富)); 

F2(测试,100);我使用一个静态的方法

请注意所以我通过的实例,但如果它是一个实例方法,我会传递到绑定的对象。 程序正好是我的静态方法中定义的类。



当然,如果你传递了错误的参数类型,那么你在运行时出现错误。我可能会寻找一种方式来设计你的程序,使尽可能多的类型信息在编译时尽可能抓获。


I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I'm looking for. So, in short, Is there some way that I can write the following:

FunctionPointer foo = // whatever, create the function pointer using mechanisms
foo();

I can't use a solid delegate (ie, using the delegate keyword to declare a delegate type) because there is no way of knowing till runtime the exact parameter list. For reference, here's what I've been toying with in LINQPad currently, where B will be (mostly) user generated code, and so will Main, and hence for nicety to my users, I'm trying to remove the .Call:

void Main()
{
    A foo = new B();
    foo["SomeFuntion"].Call();
}

// Define other methods and classes here
interface IFunction {
    void Call();
    void Call(params object[] parameters);
}

class A {
    private class Function : IFunction {
    	private MethodInfo _mi;
    	private A _this;
    	public Function(A @this, MethodInfo mi) {
    		_mi = mi;
    		_this = @this;
    	}

    	public void Call() { Call(null); }
    	public void Call(params object[] parameters) {
    		_mi.Invoke(_this, parameters);
    	}
    }

    Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();

    public A() {
    	List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
    	foreach (MethodInfo mi in typeof(Object).GetMethods())
    	{
    		for (int i = 0; i < ml.Count; i++)
    		{
    			if (ml[i].Name == mi.Name)
    				ml.RemoveAt(i);
    		}
    	}

    	foreach (MethodInfo mi in ml)
    	{
    		functions[mi.Name] = mi;
    	}
    }

    public IFunction this[string function] {
    	get { 
    		if (!functions.ContainsKey(function))
    			throw new ArgumentException();

    		return new Function(this, functions[function]);
    	}
    }
}

sealed class B : A {
    public void SomeFuntion() {
    	Console.WriteLine("SomeFunction called.");
    }
}

解决方案

You say you want to keep the number and type of parameters open, but you can do that with a delgate:

public delegate object DynamicFunc(params object[] parameters);

This is exactly the same thing you currently have. Try this:

class Program
{
    static void Main(string[] args)
    {
        DynamicFunc f = par =>
                        {
                            foreach (var p in par)
                                Console.WriteLine(p);

                            return null;
                        };

        f(1, 4, "Hi");
    }
}

You can think of an instance-method delegate as very similar to your Function class: an object an a MethodInfo. So there's no need to rewrite it.

Also function pointers in C and C++ are not any closer to what you need: they cannot be bound to an object instance and function, and also they are statically typed, not dynamically typed.

If you want to "wrap" any other method in a DynamicFunc delegate, try this:

public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
{
    return par => method.Invoke(target, par);
}

public static void Foo(string s, int n)    
{
    Console.WriteLine(s);
    Console.WriteLine(n);
}

and then:

DynamicFunc f2 = MakeDynamicFunc(null, typeof(Program).GetMethod("Foo"));

f2("test", 100);

Note that I'm using a static method Foo so I pass null for the instance, but if it was an instance method, I'd be passing the object to bind to. Program happens to be the class my static methods are defined in.

Of course, if you pass the wrong argument types then you get errors at runtime. I'd probably look for a way to design your program so that as much type information is captured at compile time as possible.

这篇关于在C#中的函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆