2011-03-13 72 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; 
    }