问题
I have some cases where I have to call method names from class names.
string scenario1 = "MockScenario1";
string scenario2 = "MockScenario2";
MockScenario1.GetInfo();
MockScenario2.GetInfo();
How can I dynamically use the strings to call method name here like
scenario1.GetInfo()
scenario2.GetInfo()
I tried to find out all options by string and control space to find related options. Any suggestions?
I am tried the below and trying to Get class name generated dynamically
The below code generated method name dynamically
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);
More clear scenario: I am trying to send class name as parameter MockScenario1 and MockScenario2 are class names.
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();
}
回答1:
How to create an instance of a type from its string representation:
string scenario1 = "TheNamespace.MockScenario1";
Type theType = this.GetType().Assembly.GetType(scenario1);
var theInstance = (MockScenario1)Activator.CreateInstance(theType);
theInstance.GetInfo();
It will be better if your classes implement a common interface, for example IGetInfoAware, and then you could write a more generic loader:
var theInstance = (IGetInfoAware)Activator.CreateInstance(theType);
Note: you need to provide the full class name for scenario1 and scenario2
See Activator.CreateInstance
EDIT:
As @Georg pointed out, if the type is not declared in the assembly of the context objects, then it is necessary first to get the assembly where the type is hosted:
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();
}
If for some reason the assembly name is unknown to you, then the type could be resolved like the following:
public Type GetTypeFromString(String typeName)
{
foreach (Assembly theAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type theType = theAssembly.GetType(typeName);
if (theType != null)
{
return theType;
}
}
return null;
}
回答2:
You can use reflection:
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(FunctionName);
theMethod.Invoke(this, userParameters);
回答3:
You could use the command design pattern. So you'd use a hash map to store your string as the key in the hash map, and then your function would be the value of the hashmap. Then when you want to call your function you say hashmap.get ("yourString"). This would return the function that you stored as your value and you could call it from there.
回答4:
I suggest using Dictionary<String, Action>
, where you can put down all the scenarios and their names e.g.
private static Dictionary<String, Action> s_Scenario =
new Dictionary<String, Action>() {
{"MockScenario1", () => MockScenario1.GetInfo()},
{"MockScenario2", () => MockScenario2.GetInfo()},
};
...
s_Scenario["MockScenario1"]();
s_Scenario["MockScenario2"]();
回答5:
Without giving Namespace
to GetType()
can return null always (I faced with that problem before adding this answer.), so it should be like this;
As you mentioned, you want to give string as parameter
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.
}
Here is my Scenario class,
class Scenario1
{
public static string GetInfo()
{
return "GetInfo() called, Scenario1";
}
}
Result; (btw GetCatsResult()
called at Form_Load
and given string which declared as string scenario1 = "Scenario1";
)
Hope helps,
回答6:
If it is for testing you can use 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");
}
}
来源:https://stackoverflow.com/questions/40242977/dynamically-calling-method-and-class-name