我们可以实例化一个刚刚声明的类的对象并传递给另一个类中的方法
我正在实现一个自动映射器并坚持这种情况:
- 在类
source
的对象中有common
对象,它只是声明但未实例化 - 当我将类
source
的对象传递给program
类的方法映射时
我怎样才能获得内部对象( 公共类对象 )的类型并实例化它?
public class common { public int x; } public class source { public common obj; } class program { static void main() { source obj = new source(); map(obj); } void map(source obj) { **how can i get type of inner object class and instantiate it** } }
我使用Type.GetType()但是给出了空。
所以map方法的工作实现:
common map(source obj) { var typeOfObj = obj.GetType().GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .First(fi=>fi.Name == "obj"); return (common) Activator.CreateInstance(typeOfObj.FieldType); }
ARCHIVED如果您需要获取obj.obj
类型,那么您可以使用:
void map(source obj){ obj.obj.GetType() ... }
但既然你还没有实例化它,那么你需要反思:
var f = typeof(source).GetField("obj"); f.FieldType // contains expected
如果私有字段是一个问题,那么你必须迭代所有解析的字段数组:
FieldInfo[] fields = source.GetFields( BindingFlags.NonPublic | BindingFlags.Instance);
并找到名为"obj"
字段
如果我错了,请纠正我的理解。
您希望在实例化source
对象后实例化内部common
对象。 如果是这样,你可以在你的source
编写一个constructor
,它将实例化你的私有common
对象。 这样的事情
class source { common obj; public source() { obj = new common(); } }
从输入对象获取类型字段信息,然后实例化该字段类型的对象并将值设置回输入对象:
// Get field info for source.obj FieldInfo fieldInfo = obj.GetType().GetField("obj", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); // Instantiate object without initializing it object instance = FormatterServices.GetUninitializedObject(fieldInfo.FieldType); // set instantiated object reference to the field source.obj fieldInfo.SetValue(obj, instance);
如果您正在制作“AutoMapper”,那么这将满足您的需求,因为它不使用构造函数,在其他答案中应该是默认(无参数)的构造函数。
在这里,您可以比较不使用默认(无参数)构造函数实例化对象的不同方法。
将以递归方式映射的完整代码示例:
public static void Main() { _genericMapInfo = typeof(Program).GetMethod("map", BindingFlags.NonPublic | BindingFlags.Static); Test t = null; map(ref t); Console.WriteLine(t == null); // False Console.WriteLine(tA); // Hello World! Console.WriteLine(tBA); // 1337 Console.WriteLine(tBB); // Hello World! } static MethodInfo _genericMapInfo; static void map(ref T obj) where T : class { if(obj == null) obj = (T)FormatterServices.GetUninitializedObject(typeof(T)); foreach(FieldInfo fInfo in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { Type fieldType = fInfo.FieldType; TypeCode tCode = Type.GetTypeCode(fInfo.FieldType); if(tCode == TypeCode.Object) { object[] param = new object[] { fInfo.GetValue(obj) }; _genericMapInfo.MakeGenericMethod(fieldType).Invoke(null, param); fInfo.SetValue(obj, param[0]); } else if(tCode == TypeCode.String) { fInfo.SetValue(obj, "Hello World!"); } else if(tCode == TypeCode.Int32) { fInfo.SetValue(obj, 1337); } } } public class Test { public string A { get; set; } public TestInside B { get; private set; } public Test() { A = "no siema"; } } public class TestInside { public int A { get; private set; } public string B { get; set; } public TestInside(int _someInteger) { A = _someInteger; } }
在线检查
如果你想要实例化你收到的类,你可以使用Activator:
Activator.CreateInstance(obj.obj.GetType());
虽然我不确定你想要实现什么。
问题出在哪里? 无需反思:
void map(source obj) { obj.obj = new common(); }
基本上你可以根据需要修改任何传递的对象,你在方法中唯一不能做的就是将obj
设置为你需要ref
-keyword的新的source
实例。 在你的情况下,你知道传递的对象的类型,所以我想你也知道相关的类包含什么,因此obj
-property的类型。
我们可以通过使用获得类型
.GetType()
方法,但当然我的情况是不同的,因为我存储了所有字段
FieldInfo[]
所以我用过
FieldInfo.FieldType
获取我的对象的类型。 一旦我们有了对象类型,我们就可以使用了
Activator.CreateInstance(Class Type);
创建类的实例。