InvokeMethod可以用作可选参数吗?

时间:2014-09-17 12:10:13

标签: c# reflection

我在项目中有基类A

有许多子类继承自A

public class A
{
    public void Process(string myString1, int myInt1   )
        {
            Type type = this.GetType();
            type.InvokeMember("ImAChildMethod", System.Reflection.BindingFlags.InvokeMethod
                                                | System.Reflection.BindingFlags.NonPublic 
                                                | System.Reflection.BindingFlags.Instance,
                                                null, 
                                                this, 
                                                new object[] { myString1, myInt1  });
        }
}

子类:

public class B:A
{
   private void ImAChildMethod(string myString, int myInt )
    {
     Console.WriteLine (myInt + ","+myString);
    }
}

所以当我执行时:

new B().Process("aaa",15);

  

15,AAA

几天过去了,现在我们需要发送 - 而不是:

new object[] { myString1, myInt1 }

new object[] { myString1, myInt1 , MyDateTime }

(但并非所有子类都使用此datetime参数)

好的,所以我们改变了(在特定的地方):

 private void ImAChildMethod(string myString, int myInt )

 private void ImAChildMethod(string myString, int myInt ,DateTime myDateTime )

问题出在哪里?

它在我们没有改变的地方引起了异常。

问题

我不想浏览所有子类并添加datetime的这个参数。 (并非所有子类都使用此参数)

有没有办法“预先识别”ImAChildMethod执行/没有,DateTime myDateTime,如果它有:使用它,如果没有 - 忽略新参数?

的Nb

我很确定我必须通过子类并添加可选参数......但我可能错了?

2 个答案:

答案 0 :(得分:3)

可选参数实际上是一个编译时功能 - 除了通过反射使信息可用

之外,CLR和框架与它们几乎没什么关系。

因此,虽然您可以检测到参数是可选的(使用ParameterInfo.IsOptional)并获取默认值(使用ParameterInfo.DefaultValue),但您需要明确地执行此操作 - InvokeMember不要为你做。

您可能希望编写一个有效的InvokeMember辅助方法,但处理可选参数...请记住,如果您只接受名称,您将会进入重载决议的尴尬业务。您可能希望将其限制为仅使用具有单个重载的名称,只是为了简单起见。

答案 1 :(得分:1)

您可以将可选参数添加到Process方法,然后检查子方法是否有两个或三个参数,然后相应地调用它:

public void Process(string myString1, int myInt1, DateTime date = default(DateTime))
{
     Type type = this.GetType();
     var flags =  BindingFlags.NonPublic | BindingFlags.Instance;
     var method = type.GetMethod("ImAChildMethod", flags);
     if(method.GetParameters().Length == 2)
     {
         type.InvokeMember("ImAChildMethod", System.Reflection.BindingFlags.InvokeMethod
                                           | System.Reflection.BindingFlags.NonPublic 
                                           | System.Reflection.BindingFlags.Instance,
                                           null, 
                                           this, 
                                           new object[] { myString1, myInt1  });
     } 
     else
     {
         type.InvokeMember("ImAChildMethod", System.Reflection.BindingFlags.InvokeMethod
                                           | System.Reflection.BindingFlags.NonPublic 
                                           | System.Reflection.BindingFlags.Instance,
                                           null, 
                                           this, 
                                           new object[] { myString1, myInt1,vdate  });
     }
}