Assembly.getCallingAssembly () 및 정적 생성자?
-
02-07-2019 - |
문제
좋아, 그래서 나는 눈썹을 올리는 다음 문제를 해결했다.
여러 가지 이유로 TestingAssembly.dll에서 테스트 클래스가 BasetestingAsembly.dll의 Testingbase 클래스에 의존하는 테스트 설정이 있습니다. 그 동안 Testbase가하는 일 중 하나는 자체적으로 특정 임베디드 리소스를 찾는 것입니다.
그래서 내 기초에 다음 줄이 포함되어 있습니다 ...
public class TestBase {
private static Assembly _assembly;
private static Assembly _calling_assembly;
static TestBase() {
_assembly = Assembly.GetExecutingAssembly();
_calling_assembly = Assembly.GetCallingAssembly();
}
}
내가 생각한 이래로,이 어셈블리는 응용 프로그램의 수명 동안 동일 할 것이므로 모든 테스트마다 그것을 다시 계산하는 이유는 무엇입니까?
그러나 이것을 실행할 때 나는 _assembly와 _calling_assembly가 각각 basetestingesmbly 및 testingasembly보다는 basetestingesmbly로 설정되고 있음을 알았습니다.
변수를 정적이 아닌 것으로 설정하고 일반 생성자로 초기화하면이 문제가 해결되었지만 왜 이런 일이 시작된 이유는 혼란 스럽습니다. 정적 생성자가 정적 멤버가 처음으로 참조 할 때 실행되었다고 생각했습니다. 이것은 내 테스트 어셈블리에서만 발생했을 수 있었으며, 그런 다음 발신자가되어야했을 것입니다. 무슨 일이 있었는지 아는 사람이 있습니까?
해결책
정적 생성자는 사용자 코드가 아닌 런타임에 의해 호출됩니다. 생성자에서 중단 점을 설정 한 다음 디버거에서 실행하여이를 볼 수 있습니다. 통화 체인의 바로 위의 기능은 기본 코드입니다.
편집하다: 정적 초기화기가 다른 사용자 코드와 다른 환경에서 실행되는 방법에는 여러 가지가 있습니다. 몇 가지 다른 방법입니다
- 그것들은 멀티 스레딩으로 인한 인종 조건으로부터 암시 적으로 보호됩니다
- 이니셜 라이저 외부에서 예외를 포착 할 수 없습니다
일반적으로 너무 정교한 것에 사용하지 않는 것이 가장 좋습니다. 다음 패턴으로 단일 이니 니트를 구현할 수 있습니다.
private static Assembly _assembly;
private static Assembly Assembly {
get {
if (_assembly == null) _assembly = Assembly.GetExecutingAssembly();
return _assembly;
}
}
private static Assembly _calling_assembly;
private static Assembly CallingAssembly {
get {
if (_calling_assembly == null) _calling_assembly = Assembly.GetCallingAssembly();
return _calling_assembly;
}
}
멀티 스레드 액세스를 기대하면 잠금을 추가하십시오.
다른 팁
나는 대답이 여기에 있다고 생각합니다. C# 정적 생성자. 가장 좋은 추측은 정적 생성자가 예기치 않은 상황에서 호출되는 것입니다.
사용자는 프로그램에서 정적 생성자가 실행되는시기를 제어 할 수 없습니다.
Assembly.getCallingAssembly ()는 통화 스택에서 두 번째 항목의 어셈블리를 반환합니다. 이는 방법/getter/생성자가 어떻게 호출되는지에 따라 매우 가능합니다. 다음은 라이브러리에없는 첫 번째 방법의 어셈블리를 얻기 위해 도서관에서 한 일입니다. (이것은 정적 생성자에서도 작동합니다.)
private static Assembly GetMyCallingAssembly()
{
Assembly me = Assembly.GetExecutingAssembly();
StackTrace st = new StackTrace(false);
foreach (StackFrame frame in st.GetFrames())
{
MethodBase m = frame.GetMethod();
if (m != null && m.DeclaringType != null && m.DeclaringType.Assembly != me)
return m.DeclaringType.Assembly;
}
return null;
}