我的项目涉及很多反思。所以,我在字典中缓存了代表。问题是我选择使用MethodInfo作为dict键,我试图使用查找方法,这是这样的:
Func<T,R> LookUp(Func<T,R> m)
{
return (Func<T,R>)dict[m.Method];
}
//LookUp(MyCls.Method)
但是,经过一些测试后,我发现用一个函数地址来提供LookUp方法,即在运行中创建过渡代表,有点慢,非常慢:
class MyCls
{
public static void Operate(int whatever){ }
}
class MainClass
{
delegate void Doer<T>(T arg);
static Dictionary<MethodInfo,Delegate> _dict = new Dictionary<MethodInfo,Delegate>();
public static void Main (string[] args)
{
Action<int> dg = MyCls.Operate;
_dict[dg.Method] = Delegate.CreateDelegate(typeof(Action<int>),dg.Method);
//performance test
var start = Environment.TickCount;
for (int i = 0; i < 10000000; i++)
{
//LookUp(dg);//11
//LookUp<int>(MyCls.Operate);//1503
//new MyCls();//431
}
Console.WriteLine (Environment.TickCount-start);
}
static Action<T> LookUp<T>(Action<T> dg)
{
//should return (Action<T>)_dict[dg.Method];
return null;
}
所以,问题是:为了提高性能,我应该改变我的方法,写一些不安全的代码(函数指针甚至是c#支持的吗?)还是有针对这种情况的替代c#式解决方案?< / p>
请帮助我离开那里!
答案 0 :(得分:1)
前段时间我使用了一个类来进行Winform应用程序中的事件聚合(Mediator),该应用程序的字典缓存类型为Key,Delegate为Value。这堂课看起来像......
public sealed class EventAggregator
{
#region Fields
private readonly Dictionary<Type, List<Object>> subscribers = new Dictionary<Type, List<Object>>();
#endregion
#region Public Methods
public void Subscribe<TMessage>(Action<TMessage> handler)
{
if (subscribers.ContainsKey(typeof(TMessage)))
{
var handlers = subscribers[typeof(TMessage)];
handlers.Add(handler);
}
else
{
var handlers = new List<Object> {handler};
subscribers[typeof(TMessage)] = handlers;
}
}
public void Unsubscribe<TMessage>(Action<TMessage> handler)
{
if (subscribers.ContainsKey(typeof(TMessage)))
{
var handlers = subscribers[typeof(TMessage)];
handlers.Remove(handler);
if (handlers.Count == 0)
{
subscribers.Remove(typeof(TMessage));
}
}
}
public void Publish<TMessage>(TMessage message)
{
if (subscribers.ContainsKey(typeof(TMessage)))
{
var handlers = subscribers[typeof(TMessage)];
foreach (Action<TMessage> handler in handlers)
{
handler.Invoke(message);
}
}
}
#endregion
}
我猜这与你想要做的有些相似。
不要查看委托本身,而是尝试查找该委托所需的类型。
答案 1 :(得分:1)
通常,从性能角度来看,使用Interfaces总是比使用delegates / reflection更好 您是否可以控制对象使用接口而不是委托?
答案 2 :(得分:0)
委托是封装函数的引用类型,因此它们本质上是函数指针。
在我看来,你正试图实现一种功能库。如果所有函数都与Func的签名匹配,那么使用它并且不要使用通用的Delegate类。
或者,如果要使用Delegate类存储具有不同签名的所有不同类型的委托,则应该使用.DynamicInvoke()方法而不是MethodInfo作为键使用更简单的东西,如字符串或函数返回值或其某些组合。
这是一个简单的例子,说明我对LookUp的各种技术的意思,
class FunctionRepository : List<Delegate> // could also be a Dictionary<,>
{
public R Invoke<R>(string name, params object[] args)
{
var _delegate = this.Single(x => x.Method.ReturnType == typeof(R)
&& x.Method.Name == name);
return (R)_delegate.DynamicInvoke(args);
}
public Func<R> LookUp<R>(string name, params object[] args)
{
var _delegate = this.Single(x => x.Method.ReturnType == typeof(R)
&& x.Method.Name == name);
return () => (R)_delegate.DynamicInvoke(args);
}
public Func<Object[], R> LookUp<R>(string name)
{
var _delegate = this.Single(x => x.Method.ReturnType == typeof(R)
&& x.Method.Name == name);
return (args) => (R)_delegate.DynamicInvoke(args);
}
}