我们可以实例化一个刚刚声明的类的对象并传递给另一个类中的方法

时间:2017-01-27 09:38:45

标签: c#

我正在实施一个自动映射器并坚持这种情况:

  1. 在类common的对象中有类source的对象,它刚刚声明但未实例化
  2. 当我将类source的对象传递给program
  3. 的方法图时

    我如何获得内部对象的类型(公共类对象)并实例化它?

    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()但是给了空。

6 个答案:

答案 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;   
    }
}

Online check

答案 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);

创建类的实例。