做框架設計時,處處需要反射,代碼冗長、效能差、難維護。C# 4.0 引入 dynamic 可**完全取代反射**,大幅簡化代碼。
原持久數據層調用日誌組件 (Zivsoft.Log.dll) 使用反射,升級為 dynamic 後:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
namespace Zivsoft.Data
{
internal class Logger
{
private static Assembly _assemblyFile;
private static dynamic _logger;
static Logger()
{
var dllPath = AppDomain.CurrentDomain.BaseDirectory + "Zivsoft.Log.dll";
if (File.Exists(dllPath))
{
_assemblyFile = Assembly.LoadFile(dllPath);
try
{
// dynamic 直接調用,無需 MethodInfo.Invoke
_logger = _assemblyFile.CreateInstance("Zivsoft.Log.Logger",
false, BindingFlags.CreateInstance, null, null, null, null);
}
catch { _logger = null; }
}
}
public static void LogInfo(string message, params object[] args)
{
_logger?.LogInfo(message, args); // 直接調用,編譯期不檢查
}
public static void LogWarning(string message, params object[] args)
=> _logger?.LogWarning(message, args);
public static void LogError(string message, params object[] args)
=> _logger?.LogError(message, args);
public static void LogDebug(string message, params object[] args)
=> _logger?.LogDebug(message, args);
public static void LogError(Exception e)
=> LogError("{0}", e);
}
}
| 維度 | 反射 | dynamic |
|---|---|---|
| 代碼行數 | 多行 (GetMethod/Invoke 等) | 單行直接調用 |
| 可讀性 | 低 | 高,像調用強型別 |
| 編譯期檢查 | 無 | 無 (運行期綁定) |
| 效能 | 較慢 | DLR 快取,通常更快 |
| IntelliSense | 無 | 無 |
作者計劃將持久數據層框架中 SQLServer、MySQL、Access 等資料庫驅動的反射調用**全部替換為 dynamic**。
dynamic 為運行期綁定,**編譯期不報錯**,拼寫錯誤只會在運行時拋出 RuntimeBinderException?. 空條件運算子防禦性編程InternalsVisibleTo 或反射