是否有可能从F(Type)到F的转变?没有反思,没有字典?

发布于 2024-08-14 08:13:22 字数 1389 浏览 5 评论 0原文

首先,简单介绍一下。

我必须起作用:

static class C
{
  static void F1(Type type)
  {
    // Do something to invoke F2<T>
  }
  static void F2<T>()
  {
    // bla bla bla
  }
}

我希望调用 F1(Type),它又应该转换到与给定类型参数相关的通用上下文,并调用通用对应的 F2F2.

简单的实现将是一个简单的反射,如下所示(为了清楚起见,我省略了绑定标志):

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();
}

:现在回答我的问题。有没有可能完全消除字典?

例如,通过使用 Reflection.Emit 发出一些奇特的函数,它将接收 Type 实例和 F2MethodInfo 并在没有字典的情况下进行转换?这个奇特的函数应该只发出一次,并且适用于任何给定的类型。我想知道是否可以通过这种方式消除任何类型的缓存映射类型到委托。

谢谢。

编辑

为了便于讨论,让我们假设奇特的发出函数知道它应该调用 F2,这意味着它不必接收其方法信息。那么可以放弃字典吗?

First, a little introduction.

I have to functions:

static class C
{
  static void F1(Type type)
  {
    // Do something to invoke F2<T>
  }
  static void F2<T>()
  {
    // bla bla bla
  }
}

I wish to invoke F1(Type), which in turn should transition to the generic context pertinent to the given type parameter and invoke the generic counterpart F2<T>.

A naive implementation would be a simple reflection, like this (I omit binding flags for clarity):

void F1(Type type)
{
  var f2MethodInfo = typeof(C).GetMethod("F2").MakeGenericMethod(type);
  f2MethodInfo.Invoke(null, new object[0]);
}

A more advanced implementation would store the open method info for F2 - typeof(C).GetMethod("F2") aside, but still it is basically the same thing.

If F1 is invoked many times and we wish to improve the performance, then the standard solution "on the market" employs a dictionary and Delegate.CreateDelegate method, like this:

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();
}

And now to my question. Is it possible to eliminate the dictionary completely?

For instance, by emitting some fancy function with Reflection.Emit which would receive a Type instance and F2MethodInfo and make the transition inside without and dictionaries? This fancy function should be emitted just once and work for any given type. I wonder if any kind of cache mapping Type to delegates can be eliminated this way.

Thanks.

EDIT

For the sake of this discussion, let us assume that the fancy emitted function knows that it should invoke F2, meaning it does not have to receive its method info. Is it possible to ditch the dictionary then?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

半边脸i 2024-08-21 08:13:22

是否可以在没有反射和字典的情况下从 F(Type) 到 F 的转换?

不,MakeGenericType 是正确的方法。

您提到发出一个奇特的函数来执行此操作;这个奇特的函数仍然需要以 call 指令结束,并且需要 MethodInfo ,就像 Delegate.CreateDelegate 一样。

您可以预先为一组已知类型生成代码,可能使用 Reflection.Emit 或 CodeDom,甚至编译时代码生成。但我想如果您预先知道类型,您就已经在字典方法中利用了这一点,对吧?

Is it possible to make the transition from F(Type) to F without reflection and without a dictionary?

No, MakeGenericType is the right approach.

You mention emitting a fancy function to do this; that fancy function will still need to end up with a call instruction, and that requires a MethodInfo in the same way that Delegate.CreateDelegate does.

You could generate code upfront for a set of known types, maybe using Reflection.Emit, or CodeDom, or even compile-time code generation. But I guess if you knew the types up front, you'd already be taking advantage of that in your dictionary approach, right?

紫罗兰の梦幻 2024-08-21 08:13:22

想想看,我的印象是,如果你想保持工作效率,你就不会摆脱字典。您可以通过发出 IL(通过 LGC、Reflection.Emit 或表达式树)来消除反射 Invoke,但您仍然必须为要使用的每种类型创建一个存根。

我想我会选择 LCG 并将这些代表存储在字典中。

Thinking of it, my impression is that you'll not get rid of the dictionary if you want to keep things efficient. You can get rid of the reflection Invoke by emitting IL (either via LGC, Reflection.Emit or Expression Tree), but you'll still have to create one stub for each type to be used.

I think I'd go with LCG and store those delegates in a dictionary.

冷默言语 2024-08-21 08:13:22

当它被多次调用时,不要多次调用 F(Type),而是将其更改为将返回 Action 类型的委托的工厂。

现在您可以用它做任何您喜欢的事情。

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();

When it is invoke many times, then do not invoke F(Type) many times, but rather change it to a factory that will return a delegate of type Action.

Now you can do whatever you like with it.

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();
面如桃花 2024-08-21 08:13:22

反方向做:

static void F1(Type type) {
    // do stuff
}

static void F2<T>() {
    F1(typeof(T))
}

没有反射性的废话,而且实际上是相同的上下文,除非您有没有告诉我们的进一步要求。

Java 的系统在这方面效果更好:

static <T> void F1(Class<T> clazz) {
    // do stuff
}

您同时拥有通用上下文和类型对象。

Do it the opposite direction:

static void F1(Type type) {
    // do stuff
}

static void F2<T>() {
    F1(typeof(T))
}

No reflect-y nonsense, and it's really the same context, unless you have further requirements you haven't told us about.

Java's system works better for this:

static <T> void F1(Class<T> clazz) {
    // do stuff
}

You have both the generic context and type object.

情愿 2024-08-21 08:13:22

你不能。可以准备委托/接口,将其作为策略包含在您的设计中,并仅在初始化时保留反射。

You can't. It is possible to prepare the delegate/interface to include it as strategy in your design, and keep reflection only in initialization time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文