C#报”TypeAccessException”的原因以及解决办法

  • Post category:C#

TypeAccessException是一种.NET平台下的异常类型,表示访问了不被许可的成员或类型。一些常见的原因是访问了私有(private),受保护(protected)或内部(internal)成员,或者访问了另一个程序集中标记为internal的成员。下面详细讲解TypeAccessException的原因以及解决办法,并提供两个示例。

一、TypeAccessException的原因

TypeAccessException通常由以下原因引起:

  1. 访问私有类型成员:TypeAccessException会在试图访问非公共类型的私有成员时抛出。访问过程中可能会使用反射API获取或设置私有成员。

  2. 访问非公共类型:TypeAccessException还可能在试图实例化非公共类型、访问非公共类型成员或调用非公共类型成员等情况下抛出。

  3. 访问internal类型成员:TypeAccessException也可能在试图从另一个程序集中访问(例如,使用反射API)标记为internal的类型成员时抛出。

二、TypeAccessException的解决办法

解决TypeAccessException,需要做的主要有以下两个方面:

  1. 修改访问修饰符:如果试图访问的类型或成员的访问修饰符为private、protected或internal,需要修改访问修饰符为public或internal。

示例一:在访问私有成员时抛出TypeAccessException

class MyClass
{
    private string privateField = "Hello World!";
}

class Program
{
    static void Main(string[] args)
    {
        var instance = new MyClass();

        // 使用反射API获取私有成员时抛出异常
        var privateFieldValue = instance.GetType()
                                       .GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance)
                                       .GetValue(instance);
    }
}

解决方法:将privateField修改为public或internal

class MyClass
{
    public string privateField = "Hello World!";
}

class Program
{
    static void Main(string[] args)
    {
        var instance = new MyClass();

        // 不会抛出TypeAccessException
        var privateFieldValue = instance.privateField;
    }
}

示例二:在访问internal成员时抛出TypeAccessException

// 程序集A
[assembly: InternalsVisibleTo("AssemblyB")] // 允许程序集B访问程序集A中的internal成员

class MyClass
{
    internal string internalField = "Hello World!";
}

// 程序集B
class Program
{
    static void Main(string[] args)
    {
        var instance = new MyClass();

        // 试图通过反射API访问internalField时抛出TypeAccessException
        var internalFieldValue = instance.GetType()
                                         .GetField("internalField", BindingFlags.NonPublic | BindingFlags.Instance)
                                         .GetValue(instance);
    }
}

解决方法:在程序集B中添加程序集A的InternalsVisibleTo属性,允许程序集B访问程序集A中标记为internal的成员。

[assembly: InternalsVisibleTo("AssemblyB")]

class MyClass
{
    internal string internalField = "Hello World!";
}

class Program
{
    static void Main(string[] args)
    {
        var instance = new MyClass();

        // 不会抛出TypeAccessException
        var internalFieldValue = instance.internalField;
    }
}
  1. 使用公共类型或成员:如果试图访问的类型或成员是public的,则可以正常访问。

示例三:访问公共类型或成员时不会抛出TypeAccessException

class MyClass
{
    public string publicField = "Hello World!";
}

class Program
{
    static void Main(string[] args)
    {
        var instance = new MyClass();

        // 不会抛出TypeAccessException
        var publicFieldValue = instance.publicField;
    }
}

综上,要解决TypeAccessException异常,需要对访问的类型或成员的访问修饰符进行修改,或使用公共类型或成员。