C# 如何从字段类型正确地实例化泛型类并将其放入数组中

C# 如何从字段类型正确地实例化泛型类并将其放入数组中,c#,generics,C#,Generics,我正在尝试创建monobhavityfield类的一个实例,并将其放入monobhavityfields数组中。我想使用T中当前字段的类型作为T。这条线 monobehaviourFields[i] = new MonobehaviourField<typeof(fieldType)>("test"); 单行为字段[i]=新的单行为字段(“测试”); 它不起作用了。如何基于fieldType创建实例并将其放入阵列中 using UnityEngine; using System.

我正在尝试创建
monobhavityfield
类的一个实例,并将其放入
monobhavityfields
数组中。我想使用
T
中当前字段的类型作为
T
。这条线

monobehaviourFields[i] = new MonobehaviourField<typeof(fieldType)>("test");
单行为字段[i]=新的单行为字段(“测试”);
它不起作用了。如何基于fieldType创建实例并将其放入阵列中

using UnityEngine;
using System.Reflection;
using System;
using System.Linq;

[Serializable]
public class MonobehaviourWrapper
{
    private MonobehaviourField<object>[] monobehaviourFields;

    public MonobehaviourWrapper(FieldInfo[] fields)
    {
        monobehaviourFields = new MonobehaviourField<object>[fields.Length];
        for (int i = 0; i < monobehaviourFields.Length; i++)
        {
            Type fieldType = fields[i].FieldType;
            monobehaviourFields[i] = new MonobehaviourField<typeof(fieldType)>("test");
        }
    }

    [Serializable]
    public class MonobehaviourField<T>
    {
        [SerializeField] private string fieldName;
        [SerializeField] private T objectContainer;
        [SerializeField] private string typeName;

        public MonobehaviourField(string fieldName)
        {
            this.fieldName = fieldName;
            this.typeName = typeof(T).FullName;
        }

        public Type FieldType { get { return Type.GetType(typeName); } }
        public T ObjectContainer { get { return objectContainer; } set { objectContainer = value; } }
        public string FieldName { get { return fieldName; } set { fieldName = value; } }
    }
}
使用UnityEngine;
运用系统反思;
使用制度;
使用System.Linq;
[可序列化]
公共类单纯形包装器
{
私有单行为字段[]单行为字段;
公共数据包(FieldInfo[]字段)
{
MonoBehaviorFields=新的MonoBehaviorField[fields.Length];
for(int i=0;i
这是可以做到的,但您需要稍微更改代码

  • 您不能拥有一个
    monobhavityfield[]
    并将
    monobhavityfield
    添加到数组中:
    monobhavityfield
    不是。为了解决这个问题,我声明了一个非泛型基类,
    monobhaviousfieldbase
    。参见,例如,有类似问题的

  • 您需要构造泛型类以生成其实例,然后使用反射调用构造函数。这里我使用从
    单行为字段
    (注意,没有指定类型参数)来创建
    单行为字段
    ,其中T是
    字段类型
    。然后我使用获取相关的构造函数,并实际调用该构造函数。请注意,
    Invoke
    返回类型为
    Object
    的实例,因此需要将其强制转换到要添加到数组的接口

  • 以下是代码(请注意,为了简洁起见,我删除了代码中不属于问题的部分):



    .

    var constructedGenericType=typeof(monobhaviorfield)。MakeGenericType(fieldType);等于null?只是用这个类尝试了一下,它不起作用,构造函数是null
    public class Tester{public float floatField;public Tester(){}
    好的。我不确定为什么
    MakeGenericType
    应该返回null。我可以理解为什么
    GetConstructor
    会返回null:我犯了一个明显的错误-传入的类型应该始终是
    typeof(string)
    ,而不是
    fieldType
    ,因为构造函数使用字符串。这在我的回答中得到了修正。当字段类型为结构时,我使用接口失败,因为不能以这种方式使用结构的协方差(例如),因此我选择了基类,
    monobhaviousfieldbase
    。更新后的示例有一个
    string
    (class)字段和一个
    float
    (struct)字段,这两个字段都适用。
    public class MonobehaviourWrapper
    {
        private MonobehaviourFieldBase[] monobehaviourFields;
    
        public MonobehaviourWrapper(FieldInfo[] fields)
        {
            monobehaviourFields = new MonobehaviourFieldBase[fields.Length];
    
            for ( int i = 0; i < monobehaviourFields.Length; i++ )
            {
                Type fieldType = fields[i].FieldType;
                var constructedGenericType = typeof(MonobehaviourField<>).MakeGenericType(fieldType);
                var constructor = constructedGenericType.GetConstructor(new Type[] { typeof(string) });
    
                object resultOfConstructor = constructor.Invoke(new object[] { "This code has worked" });
                monobehaviourFields[i] = (MonobehaviourFieldBase)resultOfConstructor;
            }
        }
    
        public IEnumerable<MonobehaviourFieldBase> MonobehaviourFields
        {
            get
            {
                return monobehaviourFields;
            }
        }
    
        public class MonobehaviourField<T> : MonobehaviourFieldBase
        {
            public MonobehaviourField(string name)
            {
                FieldName = name;
            }
        }
    }
    
    public class MonobehaviourFieldBase
    {
        private string fieldName;
    
        public string FieldName
        {
            get
            {
                return fieldName;
            }
            set
            {
                fieldName = value;
            }
        }
    }