Activator.CreateInstance在一种方法中起作用,但在另一种方法中抛出AmbiguousMatchException

时间:2018-10-07 15:54:05

标签: c# reflection

我在同一个类中有两个通用方法,每个方法都使用完全相同的代码来创建实例。一个起作用,另一个引发AmbiguousMatchException。这是代码:

private static Dictionary<Type, AccessBase> _dictionary;

public static T Access<T>(Type type) where T : AccessBase
{
    T instantiated;

    if (_dictionary.ContainsKey(type))
    {
        instantiated = _dictionary[type] as T;
    }
    else
    {
        instantiated = (T)Activator.CreateInstance(type, _manager); //<- Works!
        _dictionary.Add(type, instantiated);
    }

    return instantiated;
}        

public static void RegisterAccess<T>(Type type) where T : AccessBase
{
    if (type == null)
    {
        throw new ArgumentNullException(nameof(type));
    }

    if (_dictionary.ContainsKey(type))
    {
        return;
    }

    var instantiated = (T)Activator.CreateInstance(type, _manager); //<- Fails!
    if (instantiated == null)
    {
        throw new ArgumentException($"{nameof(type)} cannot be registered");
    }

    _dictionary.Add(type, instantiated);
}

我欢迎任何关于其原因和处理方法的建议...我一直在撕掉剩下的头发!

1 个答案:

答案 0 :(得分:0)

感谢大家的投入。我终于找到了问题,事实证明这很简单。在出现故障时,_manager字段的值为null ...一旦不再为null,它就会起作用。

要捕获此错误,我尝试与第二个方法同时调用第一个方法,但均失败。一直跟踪下去,我确定原因是空值,因为如果您稍后在此过程中进行操作,它将很好地工作。

该代码的最初目的是预先注册访问类,以便在需要它们时可以使用它们,并避免不断进行“新”调用以根据需要生成这些类。既然现在很清楚这不可能发生,那么问题是,是否完全需要这样做。如果我们稍后再进行操作,则没有太多理由这样做,因为每次打开数据库时都会重复执行此操作,并且每个数据库都不会添加,因为它已经存在。

我认为我们最终将放弃使用第二种方法(预注册)的过程,转而使用第一种方法,该方法无论如何都已使用,并且仅在需要它们并且已经起作用时才自动添加实例化的类稍后可以。