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

C# 我们可以实例化一个刚声明并传递给另一个类中方法的类的对象吗,c#,C#,我正在实现一个自动映射器,并被困在这种情况下: classsource的对象中有classcommon的对象,该对象刚刚声明,但没有实例化 当我将classsource的对象传递给program类的方法映射时 如何获取内部对象(公共类对象)的类型并实例化它 public class common { public int x; } public class source { public common obj; } class program { static voi

我正在实现一个自动映射器,并被困在这种情况下:

  • class
    source
    的对象中有class
    common
    的对象,该对象刚刚声明,但没有实例化
  • 当我将class
    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(),但给出的是空的。

    所以映射方法的工作实现:

    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);
    }
    
    已存档 如果您需要为
    obj.obj
    获取类型,则可以使用:

    void map(source obj){
       obj.obj.GetType() ...
    }
    
    但由于您尚未实例化它,因此需要进行反射:

    var f = typeof(source).GetField("obj");
    f.FieldType // contains expected
    
    void map(source obj)
    {
        obj.obj = new common();
    }
    
    如果私有字段是一个问题,那么您必须通过以下方法对所有字段数组进行迭代:

    FieldInfo[] fields = source.GetFields(
                         BindingFlags.NonPublic | 
                         BindingFlags.Instance);
    

    并定位名为“obj”的字段

    以便映射方法的工作实现:

    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);
    }
    
    已存档 如果您需要为
    obj.obj
    获取类型,则可以使用:

    void map(source obj){
       obj.obj.GetType() ...
    }
    
    但由于您尚未实例化它,因此需要进行反射:

    var f = typeof(source).GetField("obj");
    f.FieldType // contains expected
    
    void map(source obj)
    {
        obj.obj = new common();
    }
    
    如果私有字段是一个问题,那么您必须通过以下方法对所有字段数组进行迭代:

    FieldInfo[] fields = source.GetFields(
                         BindingFlags.NonPublic | 
                         BindingFlags.Instance);
    

    并找到名为“obj”的字段,如果要实例化收到的类,可以使用Activator:

    Activator.CreateInstance(obj.obj.GetType());
    

    虽然我不确定你想达到什么目的

    如果要实例化收到的类,可以使用Activator:

    Activator.CreateInstance(obj.obj.GetType());
    

    虽然我不确定你想达到什么目的

    这方面的问题在哪里?无需反思:

    var f = typeof(source).GetField("obj");
    f.FieldType // contains expected
    
    void map(source obj)
    {
        obj.obj = new common();
    }
    

    基本上,您可以根据需要修改任何传递的对象,方法中唯一不能做的就是将
    obj
    设置为
    source
    的一个新实例,您需要使用
    ref
    -关键字。在您的例子中,您知道传递对象的类型,因此我猜您也知道相关类由什么组成,从而知道
    obj
    -属性的类型

    这方面的问题在哪里?无需反思:

    var f = typeof(source).GetField("obj");
    f.FieldType // contains expected
    
    void map(source obj)
    {
        obj.obj = new common();
    }
    

    基本上,您可以根据需要修改任何传递的对象,方法中唯一不能做的就是将
    obj
    设置为
    source
    的一个新实例,您需要使用
    ref
    -关键字。在您的例子中,您知道传递对象的类型,因此我猜您也知道相关类由什么组成,从而知道
    obj
    -属性的类型

    如果我错了,请纠正我的理解

    一旦实例化了
    对象,就需要实例化内部的
    公共
    对象。如果是这样,您可以在
    源代码
    中编写一个
    构造函数
    ,它将实例化您的私有
    公共
    对象。像这样的

    class source
    { 
        common obj;
        public source()
        {
            obj = new 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(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;   
        }
    }
    
    publicstaticvoidmain()
    {
    _genericMapInfo=typeof(Program.GetMethod(“map”,BindingFlags.NonPublic | BindingFlags.Static);
    测试t=null;
    地图(参考t);
    Console.WriteLine(t==null);//False
    Console.WriteLine(t.A);//你好,世界!
    Console.WriteLine(t.B.A);/1337
    Console.WriteLine(t.B.B);//你好,世界!
    }
    静态方法信息_genericMapInfo;
    静态空隙图(参考T obj)
    T:在哪里上课
    {
    if(obj==null)
    obj=(T)FormatterServices.GetUninitializedObject(typeof(T));
    foreach(类型为(T).GetFields的FieldInfo fInfo(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
    {
    类型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(对象,参数[0]);
    }
    else if(tCode==TypeCode.String)
    {
    SetValue(obj,“你好,世界!”);
    }
    else if(tCode==TypeCode.Int32)
    {
    fInfo.SetValue(obj,1337);
    }
    }
    }
    公开课考试
    {
    公共字符串A{get;set;}
    公共证明码B{get;私有集;}
    公开考试()
    {
    A=“没有siema”;
    }
    }
    公开课证言
    {
    public int A{get;private set;}
    公共字符串B{get;set;}
    公共验证码(int\u someInteger)
    {
    A=_someInteger;
    }
    }
    

    从输入对象获取类型字段信息,然后实例化该字段类型的对象,并将值设置回输入对象:

    // 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(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;   
        }
    }
    
    publicstaticvoidmain()
    {
    _genericMapInfo=typeof(Program.GetMethod(“map”,BindingFlags.NonPublic | BindingFlags.Static);
    测试t=null;
    地图(参考t);
    Console.WriteLine(t==null);//False
    Console.WriteLine(t.A);//你好,世界!
    Console.WriteLine(t.B.A);/1337