我有一些嵌套类,如"BlueprintsManager.WorkingStandardBlueprint"和ArrayList,它们都有实例。我想把它们作为参数传递给一个方法,例如:
private void ShowBlueprints(string class_str, ArrayList class_array)
{
// class_str would be passed as "BlueprintsManager.WorkingStandardBlueprint"
// how here I can access class_str as a class and cast class_array to it, to access some variables.
// for example, I need to access some BlueprintsManager.WorkingStandardBlueprint public variables.
}
我一直在摆弄Reflections,Generics,但我仍然无法让它发挥作用。
谢谢。
您应该为此使用泛型:
private void ShowBlueprints<T>(List<T> class_array)
{
for (BlueprintsManager.WorkingStandardBlueprint item in class_array)
{
if(typeof T is BlueprintsManager.WorkingStandardBlueprint)
{
Console.WriteLine(((BlueprintsManager.WorkingStandardBlueprint)item).whateverpropertyyouhavedefined);
}
}
}
现在你可以这样调用方法:
ShowBluePrints<BlueprintsManager.WorkingStandardBlueprint>(myblueprints);
编辑在评论中,OP表示所有属性都是相同的。这个解决方案会起作用:
class BaseClass
{
string Name {get; set;}
int id {get; set;}
}
class BlueprintsManager
{
class WorkingStandardBlueprint : BaseClass
{
}
}
private void ShowBlueprints<T>(List<T> class_array) where T : BaseClass
{
for (T item in class_array)
{
Console.WriteLine(item.Name);
}
}
我认为问题在于why
而不是如何。我没有看到很多这样的构造。
如果泛型满足了您的需求,那么您应该使用泛型。
如果你真的需要从一个任意的列表中construct types dynamically
1( 制作一个通用方法(如已经建议的(
interface IBlueprint
{
int ID {get;set;}
int Name {get;set;}
}
class MyClass
{
private void ShowBlueprints<T>(IEnumerableT> values) where T : IBlueprint
{
// access properties of IBlueprint
}
// I presume you 'know something' about your 'T'-s, have an interface -
// ...if you don't you should if possible
}
2( 并这样称呼它(我从内存中输入,但它应该是正确的(
MyClass myclass = new MyClass();
var values = // list of your blueprints
// if you don't have any in the list handle it and bail out
MethodInfo methodInfo = typeof(MyClass).GetMethod("ShowBlueprints");
MethodInfo methodInfoGeneric =
methodInfo.MakeGenericMethod(new[] { values.First().GetType() });
// or get your blueprint type from string if needed
methodInfoGeneric.Invoke(myclass, new object[] { values });
不能将对象强制转换为只知道其字符串名称的类型。因此,您也不能以这种方式访问其字段。您可以选择访问以下类型的字段:
-
你知道确切的类型(或它的任何基本类型或接口(,所以你可以直接转换:
object first = class_array[0]; var blueprint = (BlueprintsManager.WorkingStandardBlueprint)first; blueprint.MyProperty = 10;
-
您不知道确切的类型,但可以肯定它有一个具有特定名称的公共属性/字段。注意这里的
dynamic
关键字,适用于C#4及更高版本。dynamic blueprint = class_array[0]; blueprint.MyProperty = 10;
-
你不知道确切的类型,但你会得到一个带有类型名称的字符串。您不知道确切的属性/字段,但您会得到一个包含属性名称的字符串。然后你可以使用反射:
string typeName = "BlueprintsManager.WorkingStandardBlueprint"; string propertyName = "MyProperty"; var type = Assembly.GetExecutingAssembly().GetType(typeName); var property = type.GetProperty(propertyName); object first = class_array[0]; // Getter: int result = (int)property.GetMethod.Invoke(first, null); // Setter property.SetMethod.Invoke(first, new object[] { 10 });
顺便说一下,您不应该使用ArrayList
。当泛型还不存在时,它是一个非常古老的类。今天你应该使用List<T>
。例如,当您知道所有T
都实现了一个接口IBlueprint
,该接口具有您想要使用的属性:
private void ShowBlueprints<T>(string classStr, List<T> classArray)
where T : IBlueprint
{
T blueprint = classArray[0];
blueprint.MyProperty = 10;
}
或者,如果您真的有任何类型的对象列表:
private void ShowBlueprints(string classStr, List<object> classArray);