如何在C#中从PHP执行这3个操作(主要是自省)
第一个问题: 在PHP中有:如何在C#中从PHP执行这3个操作(主要是自省),c#,php,oop,C#,Php,Oop,第一个问题: 在PHP中有: $b = new SomeClass(); $a = "foo"; $b->$a("something"); // This is the same as $b->foo("something"); 在C#中你是如何做到这一点的 第二个问题: 在PHP中,我可以迭代类上的每个方法,类似于: $a = new SomeClass(); // Which implements methodA, methodB; foreach($method in ge
$b = new SomeClass();
$a = "foo";
$b->$a("something"); // This is the same as $b->foo("something");
在C#中你是如何做到这一点的
第二个问题: 在PHP中,我可以迭代类上的每个方法,类似于:
$a = new SomeClass(); // Which implements methodA, methodB;
foreach($method in get_class_methods(SomeClass()))
{
$method("do stuff with each method");
}
如何在C#中执行此操作
第三项问题 PHP有一个神奇的方法
\u call()
,如果一个类没有实现一个方法,它会将其作为默认值执行,比如如果一个方法不存在,它仍然可以运行
class NewClass()
{
// constructor
__call(class name, array of parameters)
{
}
}
所以如果你这样做了
$a = new NewClass();
$a->thisDoesntExistButWorks("123","abc");
// The method gets "magically created" such as
thisDoesntExistButWorks(array with 123 and abc)....
也就是说,我会避免做这样的事情(即使是在PHP中) 在C#中没有一个PHP功能可以如此优雅地实现,但除了第三个功能之外,它们都是可以实现的 1: 2: 您可以在3.5中实现一个扩展方法ForEach()(可能在4.0的Linq库中提供),将其转化为方法链;大括号中的代码将成为lambda
好吧,在C语言中,任何内置方式都不可能实现3。您可以通过尝试在try块中反射地调用该方法来解决这个问题,捕获调用失败时抛出的任何targetException,并在catch中实现您的默认行为。您的PHP功能在C#中都无法如此优雅地实现,但除了第三个之外,它们都是可能的 1: 2: 您可以在3.5中实现一个扩展方法ForEach()(可能在4.0的Linq库中提供),将其转化为方法链;大括号中的代码将成为lambda
好吧,在C语言中,任何内置方式都不可能实现3。您可以通过尝试在try块中反射调用该方法,捕获调用失败时抛出的任何targetException,并在catch中实现默认行为来解决此问题。以下是一些基于反射的动态调用方法的资源:
以下是一些基于反射的资源,用于动态调用方法: 第一
var method_name = "my_method"
// you can change the null by the parameters you need
my_object.GetType().GetMethod(method_name).Invoke(my_object, null);
第二
第三 我不知道怎样才能在C#中做类似的事情,但如果你告诉我你的问题,肯定会有解决办法的。1
var method_name = "my_method"
// you can change the null by the parameters you need
my_object.GetType().GetMethod(method_name).Invoke(my_object, null);
第二
第三
我不知道你怎样才能在C#中做到这一点,但如果你说出你的问题,肯定会有解决办法。1和2已经被回答了不止一次。所以我将尝试3 C#不提供未知方法,因为它不必提供未知方法。如果像
a.NonExistentMethod()
那样直接调用该方法,那么程序就不会编译,在运行时捕获错误调用的想法也无关紧要
正如您已经发现的,通过执行a.GetType().GetMethod(“NoneExistentMethod”).Invoke(a,新对象[0])
,可以在运行时动态调用方法。这将因NullReferenceException
而失败,因为对GetMethod
的调用返回null。然而,这种情况是可以检测到的,所以也许我们可以对此采取一些措施。下面是一个扩展方法,其行为尽可能类似于PHP。请注意,这是未经测试的,不应在生产(甚至可能是实验)代码中使用
这可以通过执行以下操作来使用a.CallOrDefault(“方法名称”,arg1,arg2)代码>
公共静态类PhpStyleDynamicMethod
{
公共静态void\uu调用(类型@class,对象[]参数)
{
//在这里做事。
}
公共静态对象CallOrDefault(此对象b,字符串方法,params对象[]参数)
{
var methods=b.GetType().GetMethods()。其中(m=>m.Name==method&&DoParametersMatch(m.GetParameters(),parameters));
var count=methods.count();
如果(计数=1)
返回方法.Single().Invoke(b,参数);
如果(计数>1)
抛出新的ApplicationException(“无法解析单个方法”);
__调用(b.GetType(),参数);
返回null;
}
公共静态bool DoParametersMatch(ParameterInfo[]参数,对象[]值)
{
if(parameters==null&&values==null)返回true;
if(parameters==null)返回false;
if(value==null)返回false;
if(parameters.Length!=values.Length)返回false;
对于(int i=0;i
1和2已被回答多次。所以我将尝试3
C#不提供未知方法,因为它不必提供未知方法。如果像a.NonExistentMethod()
那样直接调用该方法,那么程序就不会编译,在运行时捕获错误调用的想法也无关紧要
正如您已经发现的,通过执行a.GetType().GetMethod(“NoneExistentMethod”).Invoke(a,新对象[0])
,可以在运行时动态调用方法。这将因NullReferenceException
而失败,因为对GetMethod
的调用返回null。然而,这种情况是可以检测到的,所以也许我们可以对此采取一些措施。下面是一个扩展方法,其行为尽可能类似于PHP。请注意,这是未经测试的,不应在生产(甚至可能是实验)代码中使用
这可以通过执行以下操作来使用
var method_name = "my_method"
// you can change the null by the parameters you need
my_object.GetType().GetMethod(method_name).Invoke(my_object, null);
MethodInfo[] methodInfos = typeof(MyClass).GetMethods();
foreach (MethodInfo methodInfo in methodInfos)
{
/* doing stuff... */
}
public static class PhpStyleDynamicMethod
{
public static void __call(Type @class, object[] parameters)
{
// Do stuff here.
}
public static object CallOrDefault(this object b, string method, params object[] parameters)
{
var methods = b.GetType().GetMethods().Where(m => m.Name == method && DoParametersMatch(m.GetParameters(), parameters));
var count = methods.Count();
if (count == 1)
return methods.Single().Invoke(b, parameters);
if (count > 1)
throw new ApplicationException("could not resolve a single method.");
__call(b.GetType(), parameters);
return null;
}
public static bool DoParametersMatch(ParameterInfo[] parameters, object[] values)
{
if (parameters == null && values == null) return true;
if (parameters == null) return false;
if (values == null) return false;
if (parameters.Length != values.Length) return false;
for(int i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var value = values[i];
if (!parameter.GetType().IsAssignableFrom(value.GetType()))
return false;
}
return true;
}
}