在AddComponent上调用一个函数(字符串变量)

时间:2013-07-31 11:50:48

标签: c# dynamic unity3d unity-components

Type thistype = stringVar.GetType();
thistype myScript = gameObject.AddComponent(stringVar);

myScript.runCustomFunction();

这不起作用,我相信这是因为如果我在编译时不知道变量类型(而不是运行),我就无法转换为变量类型,因此我无法直接访问组件I刚补充。

我有一个gameItem类,它从另一个脚本中提取默认值,然后将它们放入字典中。根据字典条目“functionScript”,“myScript”,我需要将myScript附加到对象,然后传递一些字典条目。

或者,我可能效率非常低,并且在myScript类中询问item类的变量,我宁愿避免。

1 个答案:

答案 0 :(得分:1)

System.Type是一种实际类型,与System.Int32System.Guid非常相似。您不能在代码中使用变量作为静态标识符,因为编译器不知道该类型是什么。

认为你要做的是根据其名称构建具体类型。

只要您知道类型名称和程序集名称,就可以使用Activator.CreateInstance执行此操作。

var typeName = "MyType";
var myType = Activator.CreateInstance("MyAssembly", typeName); 

您还可以使用dynamic关键字让DLR为您处理繁重的工作。

dynamic myType = Activator.CreateInstance("MyAssembly", typeName);
myType.runCustomFunction();

如果您的类型继承自公共基类型或实现接口,则可以将其强制转换为该类型并调用您的方法。

//Safe cast as base type
var myType = Activator.CreateInstance("MyAssembly", typeName) as BaseType;

//Or safe cast as interface
var myType = Activator.CreateInstance("MyAssembly", typeName) as IMyType;

但是,如果您的类型不是从已知类型继承,但是您知道它们都有一个名为runCustomFunction的方法,并且您不想使用dynamic那么您可以使用一点点反射到invoke that method

//Create the System.Type using assembly qualified name
var typeName = "MyType";
var assemblyQualifiedName = String.Format("MyAssembly.{0}", typeName);
var myType = Type.GetType(assemblyQualifiedName);

//Call activator overload, but `instance` is a System.Object
var instance = Activator.CreateInstance(myType);

//Use reflection to invoke the method
myType.InvokeMember(
   "runCustomFunction", //member name
   BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
   null, //default binder
   instance, //actual instance to invoke method on
   null //no arguments so we use null
);

正如您所看到的,只是让所有类型都从某个基类继承或实现一个接口要容易得多,但如果您想以艰难的方式执行它,您当然可以使用反射:)