Apa dan bagaimana cara memperbaiki kesalahan System.TypeInitializationException?

private static void Main(string[] args)
{
    string str = null;
    Logger.InitUserLogWithRotation();            // <--- error occur
    ...
}

Ketika saya membangun proyek, tidak ada kesalahan. Tetapi ketika saya mengeksekusinya, selalu dibatalkan.

Saya mencoba untuk men-debug proyek, tetapi kesalahan System.TypeInitializationException terjadi pada baris pertama.

Saya sudah mencoba googling, namun tidak menemukan solusi.

Sepertinya ada kode inisialisasi variabel yang salah, tetapi tidak dapat menemukannya.

Tolong bantu saya. Saya baru mengenal C#.

Terima kasih.

Berikut adalah Kode Kelas Logger

public class Logger
{
    private static int HDLOG_PRIORITY_DEBUG = 4;
    private static int HDLOG_PRIORITY_ERROR = 1;
    private static int HDLOG_PRIORITY_FATAL = 0;
    private static int HDLOG_PRIORITY_INFO = 3;
    private static int HDLOG_PRIORITY_WARNING = 2;
    public static int LOG_LEVEL_DEBUG = 4;
    public static int LOG_LEVEL_ERROR = 2;
    public static int LOG_LEVEL_FATAL = 1;
    public static int LOG_LEVEL_INFO = 5;
    public static int LOG_LEVEL_WARNING = 3;
    private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
    private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
    private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
    private static bool s_consoleLogging = false;
    private static FileStream s_fileStream;
    public static HdLoggerCallback s_HdLoggerCallback;
    private static string s_logDir = null;
    private static string s_logFileName = "XXXX";
    private static string s_logFilePath = null;
    public static int s_logFileSize = 0xa00000;
    private static bool s_loggerInited = false;
    private static string s_logLevels = null;
    private static int s_logRotationTime = 0x7530;
    private static string s_logStringDebug = "DEBUG";
    private static string s_logStringError = "ERROR";
    private static string s_logStringFatal = "FATAL";
    private static string s_logStringInfo = "INFO";
    private static string s_logStringWarning = "WARNING";
    private static int s_processId = -1;
    private static string s_processName = "Unknown";
    private static object s_sync = new object();
    public static int s_totalLogFileNum = 5;
    private static TextWriter writer = Console.Error;

    private static void Close()
    {
        if (!s_consoleLogging)
        {
            writer.Close();
            s_fileStream.Dispose();
            writer.Dispose();
        }
    }

    public static void Debug(string msg)
    {
        Debug("{0}", new object[] { msg });
    }

    public static void Debug(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_DEBUG, s_processName, fmt, args);
    }

    private static void DoLogRotation()
    {
    Label_0000:
        Thread.Sleep(s_logRotationTime);
        try
        {
            lock (s_sync)
            {
                FileInfo info = new FileInfo(s_logFilePath);
                if (info.Length >= s_logFileSize)
                {
                    string destFileName = s_logFilePath + ".1";
                    string path = s_logFilePath + "." + s_totalLogFileNum;
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    for (int i = s_totalLogFileNum - 1; i >= 1; i--)
                    {
                        string str3 = s_logFilePath + "." + i;
                        string str4 = s_logFilePath + "." + (i + 1);
                        if (File.Exists(str3))
                        {
                            File.Move(str3, str4);
                        }
                    }
                    File.Move(s_logFilePath, destFileName);
                }
            }
            goto Label_0000;
        }
        catch (Exception)
        {
            goto Label_0000;
        }
    }

    public static void Error(string msg)
    {
        Error("{0}", new object[] { msg });
    }

    public static void Error(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_ERROR, s_processName, fmt, args);
    }

    public static void Fatal(string msg)
    {
        Fatal("{0}", new object[] { msg });
    }

    public static void Fatal(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_FATAL, s_processName, fmt, args);
    }

    private static string GetLogDir(bool userSpecificLog)
    {
        string str;
        if (s_logDir != null)
        {
            return s_logDir;
        }
        try
        {
            if (userSpecificLog)
            {
                str = Path.Combine(s_bstUserDataDir, "Logs");
            }
            else
            {
                str = (string) Registry.LocalMachine.OpenSubKey(@"Software\XXXX").GetValue("LogDir");
            }
        }
        catch (Exception)
        {
            str = Path.Combine(s_bstUserDataDir, "Logs");
        }
        s_logDir = str;
        return str;
    }

    private static string GetPrefix(string tag, string logLevel)
    {
        int managedThreadId = Thread.CurrentThread.ManagedThreadId;
        DateTime now = DateTime.Now;
        return string.Format("{0:D4}-{1:D2}-{2:D2} {3:D2}:{4:D2}:{5:D2}.{6:D3} {7}:{8:X8} ({9}). {10}: ", new object[] { now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond, s_processId, managedThreadId, tag, logLevel });
    }

    public static TextWriter GetWriter()
    {
        return new Writer(delegate (string msg) {
            Print(msg);
        });
    }

    private static void HdLogger(int prio, uint tid, string tag, string msg)
    {
        int level = 0;
        if (prio == HDLOG_PRIORITY_FATAL)
        {
            level = LOG_LEVEL_FATAL;
        }
        else if (prio == HDLOG_PRIORITY_ERROR)
        {
            level = LOG_LEVEL_ERROR;
        }
        else if (prio == HDLOG_PRIORITY_WARNING)
        {
            level = LOG_LEVEL_WARNING;
        }
        else if (prio == HDLOG_PRIORITY_INFO)
        {
            level = LOG_LEVEL_INFO;
        }
        else if (prio == HDLOG_PRIORITY_DEBUG)
        {
            level = LOG_LEVEL_DEBUG;
        }
        Print(level, tag, "{0:X8}: {1}", new object[] { tid, msg });
    }

    public static void Info(string msg)
    {
        Info("{0}", new object[] { msg });
    }

    public static void Info(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_INFO, s_processName, fmt, args);
    }

    public static void InitConsoleLog()
    {
        InitLog("-", true, false);
    }

    public static void InitLog(string logFileName, bool userSpecificLog, bool doLogRotation)
    {
        s_loggerInited = true;
        s_HdLoggerCallback = new HdLoggerCallback(Logger.HdLogger);
        s_processId = Process.GetCurrentProcess().Id;
        s_processName = Process.GetCurrentProcess().ProcessName;
        if (logFileName == "-")
        {
            writer = Console.Error;
            s_consoleLogging = true;
        }
        else
        {
            if (logFileName == null)
            {
                logFileName = s_logFileName;
            }
            if (userSpecificLog)
            {
                logFileName = logFileName + "Users";
            }
            string logDir = GetLogDir(userSpecificLog);
            string str2 = string.Format(@"{0}\{1}.log", logDir, logFileName);
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
            s_logFilePath = str2;
            LogLevelsInit();
            lock (s_sync)
            {
                Open();
            }
            if (doLogRotation)
            {
                new Thread(() => DoLogRotation()) { IsBackground = true }.Start();
            }
        }
    }

    public static void InitSystemLog()
    {
        InitLog(null, false, false);
    }

    public static void InitSystemLogWithRotation()
    {
        InitLog(null, false, true);
    }

    public static void InitUserLog()
    {
        InitLog(null, true, false);
    }

    public static void InitUserLogWithRotation()
    {
        InitLog(null, true, true);
    }

    private static bool IsLogLevelEnabled(string tag, string level)
    {
        if (s_logLevels == null)
        {
            return false;
        }
        return (s_logLevels.StartsWith("ALL") || s_logLevels.Contains((tag + ":" + level).ToUpper()));
    }

    private static void LogLevelsInit()
    {
        string name = @"Software\XXXX\Config";
        try
        {
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(name))
            {
                s_logLevels = (string) key.GetValue("DebugLogs");
            }
        }
        catch (Exception)
        {
            return;
        }
        if (s_logLevels != null)
        {
            s_logLevels = s_logLevels.ToUpper();
        }
    }

    private static void Open()
    {
        if (!s_consoleLogging)
        {
            if (!s_loggerInited)
            {
                InitLog("-", false, false);
                s_loggerInited = true;
            }
            else
            {
                s_fileStream = new FileStream(s_logFilePath, FileMode.Append, FileAccess.Write, FileShare.Delete | FileShare.ReadWrite);
                writer = new StreamWriter(s_fileStream, Encoding.UTF8);
            }
        }
    }

    public static void Print(string msg)
    {
        Print("{0}", new object[] { msg });
    }

    public static void Print(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_INFO, s_processName, fmt, args);
    }

    public static void Print(int level, string tag, string fmt, params object[] args)
    {
        string str = "UNKNOWN";
        if (level == LOG_LEVEL_FATAL)
        {
            str = s_logStringFatal;
        }
        else if (level == LOG_LEVEL_ERROR)
        {
            str = s_logStringError;
        }
        else if (level == LOG_LEVEL_WARNING)
        {
            str = s_logStringWarning;
        }
        else if (level == LOG_LEVEL_INFO)
        {
            str = s_logStringInfo;
        }
        else if (level == LOG_LEVEL_DEBUG)
        {
            str = s_logStringDebug;
        }
        if ((level != LOG_LEVEL_DEBUG) || IsLogLevelEnabled(tag, str))
        {
            lock (s_sync)
            {
                Open();
                writer.WriteLine(GetPrefix(tag, str) + fmt, args);
                writer.Flush();
                Close();
            }
        }
    }

    public static void SetLogDir(string logDir)
    {
        s_logDir = logDir;
    }

    public static void Warning(string msg)
    {
        Warning("{0}", new object[] { msg });
    }

    public static void Warning(string fmt, params object[] args)
    {
        Print(LOG_LEVEL_WARNING, s_processName, fmt, args);
    }

    public delegate void HdLoggerCallback(int prio, uint tid, string tag, string msg);

    public class Writer : TextWriter
    {
        private WriteFunc writeFunc;

        public Writer(WriteFunc writeFunc)
        {
            this.writeFunc = writeFunc;
        }

        public override void WriteLine(string msg)
        {
            this.writeFunc(msg);
        }

        public override void WriteLine(string fmt, object obj)
        {
            this.writeFunc(string.Format(fmt, obj));
        }

        public override void WriteLine(string fmt, object[] objs)
        {
            this.writeFunc(string.Format(fmt, objs));
        }

        public override System.Text.Encoding Encoding
        {
            get
            {
                return System.Text.Encoding.UTF8;
            }
        }

        public delegate void WriteFunc(string msg);
    }
}
Larutan

Setiap kali TypeInitializationException dilemparkan, periksa semua logika inisialisasi tipe yang Anda maksud untuk pertama kalinya dalam pernyataan di mana pengecualian dilemparkan - dalam kasus Anda: Logger.

Logika inisialisasi termasuk: konstruktor statis tipe (yang - jika saya tidak melewatkannya - Anda tidak memiliki untuk Logger) dan inisialisasi field.

Inisialisasi field cukup banyak "uncritical" di Logger kecuali untuk baris-baris berikut:

private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

s_commonAppData adalah null pada titik di mana Path.Combine(s_commonAppData, "XXXX"); dipanggil. Sejauh yang saya ketahui, inisialisasi ini terjadi dalam urutan persis yang Anda tuliskan - jadi letakkan s_commonAppData setidaknya dua baris ;)

Komentar (0)

System.TypeInitializationException terjadi ketika kode yang dieksekusi selama proses pemuatan tipe melempar pengecualian.

Ketika .NET memuat tipe, ia harus mempersiapkan semua field statisnya sebelum pertama kali Anda menggunakan tipe tersebut. Terkadang, inisialisasi membutuhkan kode yang berjalan. Ketika kode tersebut gagal, Anda akan mendapatkan System.TypeInitializationException.

Dalam kasus spesifik Anda, tiga field statis berikut ini menjalankan beberapa kode:

private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

Perhatikan bahwa s_bstCommonAppData bergantung pada s_commonAppData, tetapi dideklarasikan lebih dulu dari ketergantungannya. Oleh karena itu, nilai s_commonAppData adalah null pada saat Path.Combine dipanggil, menghasilkan ArgumentNullException. Hal yang sama berlaku untuk s_bstUserDataDir dan s_bstCommonAppData: mereka dideklarasikan dalam urutan terbalik dengan urutan inisialisasi yang diinginkan.

Urutkan kembali baris-baris tersebut untuk memperbaiki masalah ini:

private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
Komentar (0)

Garis-garis ini adalah masalah Anda (atau setidaknya salah satu masalah Anda, jika ada lebih banyak):

private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

Anda mereferensikan beberapa anggota statis di inisialisasi untuk anggota statis lainnya. Ini adalah ide yang buruk, karena kompiler tidak tahu urutan inisialisasi mereka. Hasilnya adalah selama inisialisasi s_bstCommonAppData, field dependen s_commonAppData belum diinisialisasi, sehingga Anda memanggil Path.Combine(null, "XXXX") dan metode ini tidak menerima argumen null.

Anda dapat memperbaikinya dengan memastikan bahwa field yang digunakan dalam inisialisasi field lain dideklarasikan terlebih dahulu:

private static string s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
private static string s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
private static string s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");

Atau gunakan konstruktor statis untuk secara eksplisit mengurutkan penugasan:

private static string s_bstCommonAppData;
private static string s_bstUserDataDir;
private static string s_commonAppData;

static Logger()
{
    s_commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
    s_bstCommonAppData = Path.Combine(s_commonAppData, "XXXX");
    s_bstUserDataDir = Path.Combine(s_bstCommonAppData, "UserData");
}
Komentar (1)