2011-03-13 32 views
1

我正在创建一个延迟功能管理器,以便您可以拨打TimeManager.DelayedCall(uniqueid, delay, action)使actiondelay秒内被调用。但是,我遇到了一些麻烦。这是迄今为止的代码。如何从已转换为对象的匿名类型获取数据?

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,所以我无法从Think函数中获取变量ourtimeaction!有谁知道如何解决这个问题,或者如何以更好的方式做到这一点?

回答

1

编辑更正了一些细节。请参阅下面的Matti Virkkunen的评论。

您的匿名类型只在创建它的方法中具有作用域。您无法获取思考函数中的属性,因为一旦将其转换为对象并将其保存在字典中,您设置的属性就消失了。您无法将其转换回由编译器创建的原始类型,因此您无法通过反射间接访问您设置的属性。

为什么你需要使用匿名类型和对象类型呢?

基于代码贴我只是想创建一个有你需要的设置,在字典中创建和DelayData的存储实例,然后直接使用该对象从字典中的所有属性DelayData对象。

+1

对不起,同样的事情又另一篇文章 - 那里,当我开始打字都没有答案。 – Sisyphus 2011-03-13 01:11:24

+0

就是这样。最清晰的帖子通常会赢得奖品,而不是最快的帖子。 – 2011-03-13 01:15:43

+0

我想我是懒得做一个单独的类,但我想我得做,现在反正!干杯! – Dlaor 2011-03-13 01:18:53

1

嗯...你总是可以使用反射来访问你的对象中的字段,但这很慢,并且可能很丑陋(尽管最后一点是主观的)。一个更清洁的版本会涉及动态对象(但是你会失去类型安全性)。

但是,为什么你必须绝对使用匿名类型?你不能写一个小包装classstruct,然后在你的字典中使用,而不是object

+1

+1。是的,((动态)kv.Value).action()起作用。 – TrueWill 2011-03-13 02:14:37

0

为什么不创建一个新的类型

class DelayAction 
{ 
    float OurTime; 
    Action a; 
} 

,并切换到

private static Dictionary<string, DelayAction> delays = new Dictionary<string, DelayAction>(); 

公共静态无效DelayedCall(字符串ID,浮动延迟,动作一) { 延迟[ id] = new DelayAction {ourtime = time + delay,action = a}; }

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具有两个属性TimeAction

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