c# - 如何正确地从字段类型实例化泛型类并将其放入数组中
问题描述
我正在尝试创建MonobehaviourField<T>
该类的一个实例并将其放入monobehaviourFields
数组中。我想使用当前字段中的类型monobehaviourFields
as T
。这条线
monobehaviourFields[i] = new MonobehaviourField<typeof(fieldType)>("test");
不工作。如何根据 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; } }
}
}
解决方案
这可以完成,但您需要稍微更改代码。
你不能有一个
MonobehaviourField<object>[]
并添加,比如 aMonobehaviourField<string>
到数组:MonoBehaviourField
is not covariant。我已经声明了一个非泛型基类MonobehaviourFieldBase
来解决这个问题。参见,例如这个问题,它有一个类似的问题。您需要构造泛型类以创建它的实例,然后使用反射调用构造函数。这里我使用MakeGenericType来获取
MonobehaviourField<>
(注意没有指定类型参数)来创建一个MonobehaviourField<T>
where T isfieldType
。然后我Type.GetConstructor
用来获取相关的构造函数,并ConstructorInfo.Invoke
实际调用构造函数。请注意,它Invoke
返回一个类型的实例,Object
因此需要将其强制转换为要添加到数组的接口。
这是代码(请注意,为简洁起见,我删除了不属于您的问题的代码部分):
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;
}
}
}
推荐阅读
- apache - 如何重定向任何人,访问特定文件夹以使用 htaccess 接收 404 错误?
- laravel - Laravel 应用程序关闭时会触发什么事件?
- powerbi-desktop - 在 powerbi 中添加视觉效果
- sql - 标记活跃客户 - 每月至少一笔交易
- javascript - 更新从服务器获取的数据的 js 值
- javascript - 从 Array.map() 中的 Switch 语句返回
- swift - 使用 qmake 后无法使用 Xcode 签署个人资料
- javascript - 如果 Form 具有 '_blank' 属性,如何处理该窗口的关闭事件?
- flutter - 切换选项卡后防止颤动未来再次运行
- c - 理论:实现涉及搜索多个二叉树节点的函数的最有效方法