반사와 사전없이 f (유형)에서 f 로 전환 할 수 있습니까?
-
18-09-2019 - |
문제
첫째, 작은 소개.
나는 기능을해야한다 :
static class C
{
static void F1(Type type)
{
// Do something to invoke F2<T>
}
static void F2<T>()
{
// bla bla bla
}
}
호출하고 싶습니다 F1(Type)
, 차례로 주어진 유형 매개 변수와 관련된 일반 컨텍스트로 전환하고 일반적인 대응 물을 호출해야합니다. F2<T>
.
순진한 구현은 이와 같은 간단한 반사 일 것입니다 (명확성을 위해 바인딩 플래그를 생략) :
void F1(Type type)
{
var f2MethodInfo = typeof(C).GetMethod("F2").MakeGenericMethod(type);
f2MethodInfo.Invoke(null, new object[0]);
}
보다 진보 된 구현은 F2에 대한 공개 메소드 정보를 저장합니다. typeof(C).GetMethod("F2")
외쳐지만 여전히 기본적으로 같은 것입니다.
만약에 F1
여러 번 호출되고 성능을 향상시키고, "시장에서"표준 솔루션이 사전을 사용하고 Delegate.CreateDelegate
다음과 같은 방법 :
IDictionary<Type, Action> m_cache = new Dictionary<Type, Action>();
MethodInfo F2MethodInfo = typeof(C).GetMethod("F2");
void F1(Type type)
{
Action action;
if (!m_cache.TryGetValue(type, out action))
{
m_cache[type] = action = (Action)Delegate.CreateDelegate(typeof(Action), F2MethodInfo.MakeGenericMethod(type));
}
action();
}
그리고 지금 내 질문에. 사전을 완전히 제거 할 수 있습니까?
예를 들어, 유형 인스턴스와 f2methodinfo를 받고 사전없이 내부와 전환을하는 반사성으로 멋진 기능을 방출함으로써? 이 멋진 기능은 한 번만 방출해야하며 특정 유형에 따라 작동해야합니다. 대의원에게 어떤 종류의 캐시 매핑 유형을 이런 식으로 제거 할 수 있는지 궁금합니다.
감사.
편집하다
이 논의를 위해, 멋진 방출 기능이 그것이 F2를 호출해야한다는 것을 알고 있다고 가정하자. 그러면 사전을 버릴 수 있습니까?
해결책
반사와 사전없이 f (유형)에서 f 로의 전환을 할 수 있습니까?
아니, MakeGenericType
올바른 접근법입니다.
당신은 이것을하는 멋진 기능을 방출한다고 언급합니다. 그 멋진 기능은 여전히 call
교육이 필요합니다 MethodInfo
같은 방식으로 Delegate.CreateDelegate
하다.
알려진 유형 세트에 대한 코드를 생성 할 수 있습니다. 그러나 당신이 유형을 앞쪽으로 알고 있다면, 당신은 이미 당신의 사전 접근법에서 그것을 활용하고있을 것입니다.
다른 팁
그것을 생각하면, 내 인상은 당신이 일을 효율적으로 유지하려면 사전을 제거하지 않을 것이라는 것입니다. IL (LGC, Reflection.emit 또는 Expression Tree)을 통해 IL을 방출하여 반사를 제거 할 수 있지만, 각 유형을 사용할 각 유형에 대해 하나의 스텁을 만들어야합니다.
나는 LCG와 함께 가서 사전에 그 대의원을 저장할 것이라고 생각합니다.
여러 번 호출되면 F (유형)를 여러 번 호출하지 말고 유형의 대의원을 반환하는 공장으로 변경하십시오.
이제 당신은 당신이 좋아하는 것을 할 수 있습니다.
readonly IDictionary<Type, Action> _BlablasByType = new Dictionary<Type, Action>();
readonly MethodInfo _F2MethodInfo = typeof(C).GetMethod("F2");
void GetBlablaFor(Type type)
{
Action action;
if (! _BlablasByType.TryGetValue(type, out action))
{
_BlablasByType.Add(type,
action = (Action)Delegate.CreateDelegate(typeof(Action),
_F2MethodInfo.MakeGenericMethod(type));
}
return action;
}
var blabla = GetBlablaFor(typeof(Abc));
for(int i = 0; i < 10000; i++)
blabla();
반대 방향으로하십시오.
static void F1(Type type) {
// do stuff
}
static void F2<T>() {
F1(typeof(T))
}
넌센스는 없으며, 우리에게 말하지 않은 추가 요구 사항이 없다면 실제로 동일한 상황입니다.
Java의 시스템은 다음을 위해 더 잘 작동합니다.
static <T> void F1(Class<T> clazz) {
// do stuff
}
일반적인 컨텍스트와 타입 객체가 모두 있습니다.
당신은 할 수 없습니다. 디자인에 전략으로 포함하도록 대의원/인터페이스를 준비하고 초기화 시간에만 반영을 유지할 수 있습니다.