我正在实施一个自动映射器并坚持这种情况:
common
的对象中有类source
的对象,它刚刚声明但未实例化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()但是给了空。
答案 0 :(得分:2)
所以正在实施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"
答案 1 :(得分:1)
在实例化common
对象后,您希望实例化内部source
对象。如果是这样,您可以在constructor
内写一个source
,它将实例化您的私人common
对象。像这样的东西
class source
{
common obj;
public source()
{
obj = new common();
}
}
答案 2 :(得分:1)
从输入对象获取类型字段信息,然后实例化该字段类型的对象并将值设置回输入对象:
// 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”,那么这将符合您的需求,因为它不使用构造函数,在其他答案中应该是默认的(无参数)。
Here您可以比较不使用默认(无参数)构造函数实例化对象的不同方法。
将以递归方式映射的完整代码示例:
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(t.A); // Hello World!
Console.WriteLine(t.B.A); // 1337
Console.WriteLine(t.B.B); // Hello World!
}
static MethodInfo _genericMapInfo;
static void map<T>(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;
}
}
答案 3 :(得分:0)
如果您想要实例化您收到的课程,您可以使用Activator:
Activator.CreateInstance(obj.obj.GetType());
虽然我不确定你想要达到的目标。
答案 4 :(得分:0)
问题出在哪里?无需反思:
void map(source obj)
{
obj.obj = new common();
}
基本上你可以根据需要修改任何传递的对象,你在方法中唯一不能做的就是将obj
设置为source
的新实例,你需要它ref
- 关键字。在你的情况下,你知道传递的对象的类型,所以我猜你也知道有关的类包含什么,因此知道obj
- 属性的类型。
答案 5 :(得分:0)
我们可以使用
获取类型.GetType()
方法但当然我的情况不同,因为我将所有字段存储在
中FieldInfo[]
所以我用了
FieldInfo.FieldType
获取我的对象的类型。 一旦我们的对象类型,我们就可以使用
Activator.CreateInstance(Class Type);
创建类的实例。