我正在创建一个延迟的函数管理器,以便您可以调用TimeManager.DelayedCall(uniqueid, delay, action)
以在action
秒内调用delay
。但是,我遇到了一些麻烦。这是迄今为止的代码。
private static Dictionary<string, object> delays = new Dictionary<string, object>();
public static void Think(float dt)
{
timestep = dt * timescale;
time += timestep;
foreach (KeyValuePair<string, object> kv in delays)
{
if (time > kv.Value.ourtime)
{
kv.Value.action();
}
}
}
public static void DelayedCall(string id, float delay, Action a)
{
delays[id] = new { ourtime = time + delay, action = a };
}
此代码无法编译。因为我正在将匿名类型从DelayedCall
函数转换为object
,所以我无法在ourtime
函数中从中获取变量action
和Think
!有谁知道如何解决这个问题,或者如何以更好的方式做到这一点?
答案 0 :(得分:1)
嗯......您总是可以使用反射来访问对象中的字段,但这很慢,而且可能很难看(尽管最后一点是主观的)。更干净的版本将涉及动态对象(但是你会失去类型安全性)。
但为什么你绝对要使用匿名类型?难道你不能写一个小包装class
或struct
,然后在你的字典中使用它而不是object
吗?
答案 1 :(得分:1)
您可以使用反射:
Action a = () => { Console.Write("Hello"); };
object o = new { ourtime = DateTime.Now, action = a };
DateTime ourtime = (DateTime) o.GetType().GetProperties()[0].GetValue(o, null);
Action action = (Action) o.GetType().GetProperties()[1].GetValue(o, null) ;
但创建一个新类型来保存这些值会更加清晰,例如TimedAction
包含两个属性Time
和Action
答案 2 :(得分:1)
我摆脱了AnonymousType。它只是让事情变得不清楚,并且可能通过添加错误的类型来增加字典中的值。我还添加了一些Linq,并使用了List.ForEach。
public class Thing
{
public double ourtime;
public Action action;
}
public class Program
{
private readonly Dictionary<string, Thing> delays = new Dictionary<string, Thing>();
public void Think(float dt)
{
timestep = dt * timescale;
time += timestep;
var actions = delays.Where(d => time > d.Value.ourtime).Select(d => d.Value.action).ToList();
actions.ForEach(a => a());
}
public void DelayedCall(string id, float delay, Action a)
{
delays[id] = new Thing { ourtime = time + delay, action = a };
}
答案 3 :(得分:1)
EDIT在此修正了一些细节。请参阅Matti Virkkunen的评论。
您的匿名类型仅在您创建它的方法中具有范围。您无法在think函数中获取属性,因为一旦将其转换为对象并将其保存在字典中,您设置的属性就会消失。您无法将其强制转换为由编译器,因此您无法通过反射间接访问您设置的属性。
为什么需要使用匿名类型和对象类型?
基于发布的代码,我将创建一个DelayData对象,该对象具有在字典中设置,创建和存储DelayData实例所需的所有属性,然后直接从字典中使用该对象。
答案 4 :(得分:0)
我会编写一个包含两个属性的小类,并使用它而不是匿名类。另一个选择是切换到动态对象,并放弃类型安全。
答案 5 :(得分:0)
为什么不创建新类型
class DelayAction
{
float OurTime;
Action a;
}
并改为
private static Dictionary<string, DelayAction> delays = new Dictionary<string, DelayAction>();
和
public static void DelayedCall(string id,float delay,Action a) { 延迟[id] =新的DelayAction {ourtime = time + delay,action = a}; }
答案 6 :(得分:0)
我制作扩展方法ToDictionary
object anonymous = new
{
Id = 1234,
Password = "pwd",
};
var dictionary = anonymous.ToDictionary();
和扩展方法如下。
public static IDictionary<string, dynamic> ToDictionary<T>(this T target, bool exceptDefaultValue = false)
where T : class
{
if (target == null)
{
throw new ArgumentNullException("target");
}
IDictionary<string, dynamic> dictionary = new Dictionary<string, dynamic>(System.StringComparer.OrdinalIgnoreCase);
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(target))
{
object value = propertyDescriptor.GetValue(target);
if (exceptDefaultValue == true)
{
if (value == null || value.Equals(propertyDescriptor.PropertyType.DefaultValue()) == true)
{
continue;
}
}
dictionary.Add(propertyDescriptor.Name, value);
}
return dictionary;
}