2013-11-25 24 views
1

我試圖使IL代碼屬性setter委託的委託。當前的代碼工作正常的字符串,但爲int,布爾,日期時間(所有值類型)我得到「操作可能會破壞運行時」。我試圖做一個創建從屬性的setter

DynamicMethod method = new DynamicMethod("Setter", typeof (void), new[] 
     { 
      typeof (T), typeof (Object) 
     }, true); 
     var ilgen = method.GetILGenerator(); 
     ilgen.Emit(OpCodes.Ldarg,0); 
     ilgen.Emit(OpCodes.Castclass, property.DeclaringType); 
     ilgen.Emit(OpCodes.Ldarg,1); 
     ilgen.Emit(OpCodes.Unbox_Any, property.PropertyType); 
     ilgen.Emit(OpCodes.Box,property.PropertyType); 
     ilgen.Emit(OpCodes.Call, property.GetSetMethod()); 
     ilgen.Emit(OpCodes.Ret); 
     var action = method.CreateDelegate(typeof (Action<T, Object>)) as Action<T, Object>; 
     return action; 


     //var target = Expression.Parameter(typeof(T), "obj"); 
     //var value = Expression.Parameter(typeof(Object), "value"); 
     //var body = Expression.Assign(
     //        Expression.Property(Expression.Convert(target, property.DeclaringType), property), 
     //        Expression.Convert(value, property.PropertyType)); 

     //var lambda = Expression.Lambda<Action<T, Object>>(body, target, value); 

     //return lambda.Compile(); 

我已經使用拆箱和箱,試圖得到詮釋工作這兩條線也可以是castclass和字符串會工作,但仍然得到同樣的錯誤值類型。

我使用IL代碼,以儘量避免轉換在我的舊代碼所示。我試圖避免轉換,因爲此代碼需要儘可能快。

回答

1

您知道屬性的類型,所以你可以生成相應的代碼。如果它是一個引用類型,那麼你必須投射,如果它是一個值類型,那麼你必須解開。這工作得很好:

ilgen.Emit(OpCodes.Ldarg, 1); 
    if (property.PropertyType.IsValueType) 
     ilgen.Emit(OpCodes.Unbox_Any, property.PropertyType); 
    else ilgen.Emit(OpCodes.Castclass, property.PropertyType);