라떼군 이야기
.net Reflection을 사용하는 코드에서 GetMethod의 Name Null 문제
Problem
아래와 같이 Reflection
을 이용해 호출하는 메소드의 파라미터와 이름을 추출하여 동작하는 코드가 있었다.
관리하지 않은 오래된 코드였고, 최근에 업데이트가 필요한 부분이 생겨 수정되었다.
업데이트 과정에서 알게된 문제로 개발 환경에서는 문제가 없이 잘 동작했지만 라이브 환경에서 실행에 문제가 있었다.
직접적인 에러가 표기되지 않아 로깅을 통해서 라이브 환경에서 디버깅 하였고, 결국 paramNames[index++].Name
부분에서 Name
은 항상 Null
인 것이 문제임을 확인할 수 있었다.
사용한 코드의 일부는 아래와 같다.
using System.Reflection;
...(중략)
public string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
protected R ContextTemplate<R>(string procedureName, params object[] paramData)
{
this.connection = new SqlConnection(ConnectionString);
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
var paramNames = methodBase.GetParameters();
using (connection)
{
var param = new DynamicParameters();
var index = 0;
foreach (var paramData in paramData)
{
param.Add(paramNames[index++].Name, paramData); // 문제 되는 부분
}
...(중략)
return result.SingleOrDefault();
}
}
Solution
디버그 모드에서 StackFrame
은 작동하지만 코드 최적화 모드가 켜져있는 릴리즈 모드에서는 해당 스택이 예상과 다르게 동작할 수 있었다1.
즉, 이것은 코드 최적화가 되지 않은 빌드에서만 동작하는 코드였던 것이다.
해당 라이브러리의 최적화를 꺼놓은 상태로 빌드해 문제없이 동작하긴 하겠지만,
비슷한 코드를 사용하고 있다면 다른 방법으로 동작하도록 코드를 재작성 하는 것이 좋겠다.