代码之家  ›  专栏  ›  技术社区  ›  Bas Smit

当您知道要分配给的字段的名称时,可以将数组分配给未知类型的数组吗?

  •  2
  • Bas Smit  · 技术社区  · 16 年前

    我需要给一个字段分配一个数组。我不知道字段类型,但我确实有对实例和字段名称的引用。我可以假设数组可以强制转换为字段类型。能做到吗?

    制动辅助系统

    编辑:

    希望这段代码能够说明我要做什么,这会导致分配中出现异常:

    class MyClass
    {
        static void Main()
        {
            MyClass t = new MyClass();
            A a = new A();
            C[] c = new C[] {new B()};
            t.Assign(a, "field", c);
        }
    
        void Assign(object obj, string field, object[] value)
        {
            // crashes
            obj.GetType().GetField(field).SetValue(obj, value);
        }
    }
    
    class A
    {
        public B[] field;
    }
    
    class B : C { }
    
    class C { }
    
    4 回复  |  直到 16 年前
        1
  •  5
  •   Darin Dimitrov    16 年前
    instance.GetType()
        .GetField("fieldName", BindingFlags.Instance | BindingFlags.NonPublic)
        .SetValue(instance, array);
    
        2
  •  1
  •   ChrisF    16 年前

    有关更多信息,请参阅 reflection page on MSDN .

        3
  •  0
  •   Grizzly    16 年前

    如果调用它的代码不是时间关键型的,您可以简单地使用fieldinfos setvalue()。

    obj.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(obj, newFieldValue);
    

    如果代码调用更频繁,您可能希望动态编译setter委托。可以这样做,例如使用轻量级代码生成:

    Action<TObject, TField> ConstructGetter(string fieldName)
    {
        System.Reflection.FieldInfo field = typeof(TObject).GetField(fieldName);
        DynamicMethod method = new DynamicMethod(typeof(TObject).ToString() + ":" + "Set:" + name,
                                                 null, new Type[] { typeof(TObject), typeof(TField) }, typeof(TObject));
        ILGenerator generator = method.GetILGenerator();
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Ldarg_1);
        generator.Emit(OpCodes.Stfld, field);
        generator.Emit(OpCodes.Ret);
        return method.CreateDelegate(typeof(Action<TObject, TField>)) as Action<TObject, TField>;
    }
    
        4
  •  0
  •   Bas Smit    16 年前

    所以一个善良的灵魂向我展示了解决方案,享受吧:)

    using System;
    using System.Reflection;
    
    class MyClass
    {
        static void Main()
        {
            MyClass t = new MyClass();
            A a = new A();
            C[] c = new C[] {new B()};
            t.Assign(a, "field", c);
        }
    
        void Assign(object obj, string field, object[] value)
        {
            FieldInfo pinfo = obj.GetType().GetField(field);
            Array array = Array.CreateInstance(pinfo.FieldType.GetElementType(), value.Length);
            value.CopyTo(array, 0);
            pinfo.SetValue(obj, array);
        }
    }
    
    class A
    {
        public B[] field;
    }
    
    class B : C { }
    
    class C { }