Domanda

I am trying to make a property setter delegate in il code. The current code works fine for a string but for int, bool, datetime (all value types) i get "Operation could destabilize the runtime".

 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();

I have used unbox and box to try and get int working this two lines can also be a castclass and string will work but still get same error with value types.

I am using il code to try and avoid conversion as seen in my old code. I am trying to avoid conversion as this code needs to be as fast as possible.

È stato utile?

Soluzione

You know the type of the property so you can just generate the appropriate code. If it is a reference type then you have to cast, if its a value type then you have to unbox. This worked well:

    ilgen.Emit(OpCodes.Ldarg, 1);
    if (property.PropertyType.IsValueType)
         ilgen.Emit(OpCodes.Unbox_Any, property.PropertyType);
    else ilgen.Emit(OpCodes.Castclass, property.PropertyType);            
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top