动态调用方法和类名

时间:2016-10-25 14:43:45

标签: c# .net class

我有一些情况需要从类名调用方法名。

string scenario1 = "MockScenario1";
string scenario2 = "MockScenario2";

MockScenario1.GetInfo();
MockScenario2.GetInfo();

如何动态使用字符串来调用方法名称,如

scenario1.GetInfo()
scenario2.GetInfo()

我试图通过字符串和控制空间找出所有选项来查找相关选项。有什么建议吗?

我尝试了以下内容并尝试动态生成类名

以下代码生成的方法名称动态

string methodName = "hello";

//Get the method information using the method info class
 MethodInfo mi = this.GetType().GetMethod(methodName);

//Invoke the method
// (null- no parameter for the method call
// or you can pass the array of parameters...)
mi.Invoke(this, null);

更明确的情况: 我正在尝试将类名作为参数发送 MockScenario1和MockScenario2是类名。

string scenarioCats = "MockScenario1";
string scenarioDogs = "MockScenario2";
GetResult(scenarioCats);
GetResult(scenarioDogs);

public static void GetCatsResult(string scenarioCats){
scenarioCats obj = new scenarioCats();
    obj.GetInfo();    
}
public static void GetDogsResult(string scenarioDogs){
scenarioDogs obj = new scenarioDogs();
    obj.GetInfo();    
}

6 个答案:

答案 0 :(得分:15)

如何从字符串表示形式创建类型的实例:

string scenario1 = "TheNamespace.MockScenario1";
Type theType = this.GetType().Assembly.GetType(scenario1);
var theInstance = (MockScenario1)Activator.CreateInstance(theType);
theInstance.GetInfo();

如果你的类实现了一个通用接口,例如 IGetInfoAware ,那么你会写一个更通用的加载器会更好:

var theInstance = (IGetInfoAware)Activator.CreateInstance(theType);

注意:您需要提供scenario1和scenario2的完整类名

请参阅https://jsfiddle.net/4yczepsj/

修改

正如@Georg指出的那样,如果未在上下文对象的程序集中声明类型,那么首先需要获取托管类型的程序集:

var theAssembly = (
    from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
    where (assembly.FullName == "TheNamespace.AssemblyName")
    select assembly
)
.FirstOrDefault();

if ( theAssembly!= null ){
    Type theType = theAssembly.GetType(scenario1);
    var theInstance = (IGetInfoAware)Activator.CreateInstance(theType);
    theInstance.GetInfo();
}

如果由于某种原因您不知道程序集名称,则可以解析类型如下:

public Type GetTypeFromString(String typeName)
{
    foreach (Assembly theAssembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        Type theType = theAssembly.GetType(typeName);
        if (theType != null)
        {
            return theType;                    
        }
    }
    return null;
}

答案 1 :(得分:5)

您可以使用反射:

Type thisType = this.GetType();
MethodInfo theMethod =      thisType.GetMethod(FunctionName);
theMethod.Invoke(this, userParameters);

答案 2 :(得分:3)

您可以使用命令设计模式。因此,您使用哈希映射将字符串存储为哈希映射中的键,然后您的函数将是哈希映射的值。然后,当你想调用你的函数时,你会说hashmap.get(" yourString")。这将返回您存储为值的函数,您可以从那里调用它。

答案 3 :(得分:3)

我建议使用Dictionary<String, Action>,您可以在其中放下所有方案及其名称,例如

private static Dictionary<String, Action> s_Scenario = 
  new Dictionary<String, Action>() {
    {"MockScenario1", () => MockScenario1.GetInfo()},
    {"MockScenario2", () => MockScenario2.GetInfo()}, 
  }; 

...

s_Scenario["MockScenario1"]();  
s_Scenario["MockScenario2"](); 

答案 4 :(得分:2)

不给Namespace GetType()总是可以返回null(我在添加这个答案之前遇到了这个问题。),所以它应该是这样的;

正如您所提到的,您希望将字符串作为参数

public void GetCatsResult(string scenarioCats)
        {
            string item = this.GetType().Namespace + "." + scenarioCats; 
            // combined class string with the namespace
            Type className = Type.GetType(item);
            // found the class
            MethodInfo m = className.GetMethod("GetInfo");
            // get the method from class
            object value = m.Invoke(null,null);
            // invoke and value will represent the return value.
        }

这是我的Scenario类,

class Scenario1
    {
        public static string GetInfo()
        {
            return "GetInfo() called, Scenario1";
        }
    }

结果; (btw GetCatsResult()Form_Load调用,并给出声明为string scenario1 = "Scenario1";的字符串

enter image description here

希望有所帮助,

答案 5 :(得分:0)

如果是用于测试,可以使用PrivateObject:

using Microsoft.VisualStudio.TestTools.UnitTesting;

class Class1
{
    public Class1()
    {
        MyClass myClass = new MyClass();
        PrivateObject myClassPrivateObject = new PrivateObject(myClass, new PrivateType(typeof(MyClass)));

        myClassPrivateObject.Invoke("MyMethod");
    }
}