문제

첫째, 작은 소개.

나는 기능을해야한다 :

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
}

일반적인 컨텍스트와 타입 객체가 모두 있습니다.

당신은 할 수 없습니다. 디자인에 전략으로 포함하도록 대의원/인터페이스를 준비하고 초기화 시간에만 반영을 유지할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top