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);
}
}
34
3
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:s_commonAppData
adalahnull
pada titik di manaPath.Combine(s_commonAppData, "XXXX");
dipanggil. Sejauh yang saya ketahui, inisialisasi ini terjadi dalam urutan persis yang Anda tuliskan - jadi letakkans_commonAppData
setidaknya dua baris ;)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:
Perhatikan bahwa
s_bstCommonAppData
bergantung padas_commonAppData
, tetapi dideklarasikan lebih dulu dari ketergantungannya. Oleh karena itu, nilais_commonAppData
adalahnull
pada saatPath.Combine
dipanggil, menghasilkanArgumentNullException
. Hal yang sama berlaku untuks_bstUserDataDir
dans_bstCommonAppData
: mereka dideklarasikan dalam urutan terbalik dengan urutan inisialisasi yang diinginkan.Urutkan kembali baris-baris tersebut untuk memperbaiki masalah ini:
Garis-garis ini adalah masalah Anda (atau setidaknya salah satu masalah Anda, jika ada lebih banyak):
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 dependens_commonAppData
belum diinisialisasi, sehingga Anda memanggilPath.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:
Atau gunakan konstruktor statis untuk secara eksplisit mengurutkan penugasan: