【问题标题】:Activator.CreateInstance(Type T) returns nullActivator.CreateInstance(Type T) 返回 null
【发布时间】:2019-06-25 06:27:58
【问题描述】:

编辑:此代码统一作为自定义检查器代码运行,但我不确定它是否相关,如果是,我将发布整个课程。

我想获取所有实现特定接口的类,并显示一个选项列表,以便用户选择如何实现该接口。

这是一个描述角色行为的简单界面。

我曾尝试将接口替换为抽象类,但无济于事...

在调试中我可以看到,返回的值为空。

我在网上找到的所有内容都说该类型可能不存在,但在我的情况下这是不可能的,因为我使用反射获得了我的类型。

ICombatBehaviour combat;
private string[] FindAllCombatOptions(out List<Type> existingTypes)
{
    List<string> options = new List<string>();
    existingTypes = new List<Type>();
    var combatBehaviours = Assembly.GetAssembly(typeof(ICombatBehaviour)).GetTypes()
        .Where(myType => myType.IsClass && !myType.IsAbstract && typeof(ICombatBehaviour).IsAssignableFrom(myType));
    foreach (var behaviour in combatBehaviours)
    {
        existingTypes.Add(behaviour);
        options.Add(behaviour.Name);
    }
    return options.ToArray();
}
private void UpdateType(List<Type> types)
{
    combat = Activator.CreateInstance(types[index]) as ICombatBehaviour;
}

UpdateType() 方法,获取FindAllCombatOptions() 方法找到的所有类型,并获取所选索引中的类型。类型正确,但combat 变量仍然为空...

ICombatBehavior:

public interface ICombatBehaviour
{

}

实现类:

public class FightBehaviour : ICombatBehaviour
{

}

public class EscapeBehaviour : ICombatBehaviour
{

}

这是调用函数:

public override void SelectType()
    {
        List<Type> types;
        string[] options = FindAllCombatOptions(out types);
        index = AskUserForAType(options); // Currently returns only zero
        UpdateType(types);
    }

【问题讨论】:

  • 您发布的代码似乎运行良好,如 here 所示。鉴于此,如果您共享更多代码可能会有所帮助,例如定义这些成员的整个类、它们的使用方式以及实现 ICombatBehaviour 的类型示例
  • 您确定该索引上的类型实现了 ICombatBehaviour?
  • @OndřejKubíček 我敢肯定,因为如您所见,FindAllCombatOptions() 方法只找到实现该接口的类
  • 您应该将Activator.CreateInstance(…) as ICombatBehaviour 更改为(ICombatBehaviour)Activator.CreateInstance(…),因为您希望此时所有类型都派生自ICombatBehaviour。如果有一个不是从它派生的类型,它会抛出一个异常并告诉你出了什么问题,而不是默默地以 null 失败,你不知道为什么会像现在这样。
  • 不客气。您可以添加答案并接受它,这样有相同问题的新手可以轻松找到解决方案,而无需阅读所有 cmets。 :-D

标签: c# reflection interface null createinstance


【解决方案1】:

请在 UpdateType 方法中创建类型之前加载所有程序集。

private void UpdateType(List<Type> types)
{
    for(int index =0; index < types.Count; index++)
    {
          Assembly.Load(types[index].Assembly.FullName);
          combat = Activator.CreateInstance(types[index]) as ICombatBehaviour;

    }
}

希望这会有所帮助。

【讨论】:

  • 我得到一个错误,没有这样的重载 Assembly.Load(Assembly)...
  • 我忘了添加 fullName 属性。现在应该可以了。
  • 不,我仍然得到一个空值......我不明白为什么它不起作用......
  • 您是否检查过您在“ types[index]”中发送的类型是否可分配给 ICombatBehavior ?我相信该类型不是从 ICombatBehavior 继承的。
【解决方案2】:

解决方案非常简单。问题不在于代码,而在于 Unity3D。

Unity 将 FightBehaviourEscapeBehaviour 类创建为 MonoBehaviour 类,无法实例化。因此我需要将其设置为普通类。

感谢cmets中帮助过我的每一个人,我真的很感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多