# WPF Databinding with RubyObjects, continuation, dynamically create wrappers with strong typed proper

**URL:** <https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301>\
**Category:** IronRuby\
**Created:** [June 14, 2011, 5:47pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301 "2011-06-14T17:47:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [June 14, 2011, 5:47pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301/1 "2011-06-14T17:47:39Z")

</div>

Hello,

I recently stumbled upon this awesome code:  
[http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html](http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html)  
It does exactly what I need; dynamically wrapping my RubyObject into a  
CLR class with CLR properties, except that it’s designed only for string  
properties.

I’ve adjusted the code to support a number of types, incl int, bool and  
float.

However the CLR crashes when-ever I assign a value to a non-string  
property, e.g float or int.  
“The runtime has encountered a fatal error. The address of the error was  
at 0x5935788d, on thread 0x1adc. The error code is 0xc0000005. This  
error may be a bug in the CLR or in the unsafe or non-verifiable  
portions of user code. Common sources of this bug include user  
marshaling errors for COM-interop or PInvoke, which may corrupt the  
stack.”

Any assistance would be deeply appreciated.

In essence, instead of using typeof(string) inside the  
TypeGenerator.Generate method, i use e.g; typeof(int) or typeof(float)  
This is my current code:

C#:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Reflection;  
using System.Reflection.Emit;

namespace GenerateType  
{  
public class TypeGenerator  
{  
public delegate object GetPropertyDelegate(string propertyName);  
public delegate object SetPropertyDelegate(string propertyName,  
object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)  
{  
AssemblyName asmName = new AssemblyName(“BindingTypes”);  
AssemblyBuilder asmBuilder =  
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);  
ModuleBuilder modBuilder =  
asmBuilder.DefineDynamicModule(“Types”);  
TypeBuilder typeBuilder = modBuilder.DefineType(className,  
TypeAttributes.Public |  
TypeAttributes.Class |  
TypeAttributes.AutoClass |  
TypeAttributes.AnsiClass |  
TypeAttributes.BeforeFieldInit |  
TypeAttributes.AutoLayout);

```
        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);  
FieldBuilder setFieldBuilder =  
typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)
        {
            type = null;
            switch (s)
            {
                case "float":
                    type = typeof(float);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "bool":
                    type = typeof(bool);
                    break;
                //case "dynamic":
                // type = dynamic;
            }
            if (type != null)
            {
                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);  
}  
}  
return typeBuilder.CreateType();  
}

```
    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)  
{  
foreach (string propertyName in properties)  
{  
PropertyBuilder propBuilder =  
typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type[] {});  
MethodBuilder getter = typeBuilder.DefineMethod(“get\_” +  
propertyName,  
getSetAttr,  
type,  
Type.EmptyTypes);

```
            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Ret);

```
            // Define the "set" accessor method for CustomerName.
            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,  
getSetAttr,  
null,  
new Type[] { type });

```
            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Pop);  
ilGen.Emit(OpCodes.Ret);

```
            // Last, we must map the two methods created above to 

```

our PropertyBuilder to  
// their corresponding behaviors, “get” and “set”  
respectively.  
propBuilder.SetGetMethod(getter);  
propBuilder.SetSetMethod(setter);  
}  
}  
}  
}

Ruby Code:

include System::Data  
include System::Windows::Data  
include System::ComponentModel

include GenerateType  
class WrapperGenerator  
def initialize  
@wrapper\_cache = {}  
end

def wrap(ruby\_object)  
if ruby\_object.is\_a? Array  
ruby\_object.map {|o| wrap(o) }  
else  
cache(ruby\_object) unless cached(ruby\_object)  
wrapper\_class = cached(ruby\_object)  
wrapper\_class.new(ruby\_object)  
end  
end

def invalidate  
@wrapper\_cache.clear  
end  
private  
def cached(object)  
@wrapper\_cache[object.class.name]  
end

def cache(object)  
@wrapper\_cache[object.class.name] = generate\_wrapper(object)  
end

def generate\_wrapper(object)  
wrapper\_name = “#{object.class.name}Wrapper”  
properties = Dictionary.of(System::String,  
List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)
  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|
    properties[k.to_clr_string] = List.of(System::String).new
    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}
  end
else
  # Default to String properties
  properties["string"] = List.of(System::String).new
  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}  
end

```
wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)  
base\_instance = System::Activator.create\_instance wrapper\_base\_type

```
eval <<EOS
  class #{wrapper_name} < base_instance.class
    def initialize(original)
      self.on_get = lambda do |prop|
        original.send prop
      end

      self.on_set = lambda do |prop, val|
        original.send "\#{prop}=", val
      end
    end
  end
  return #{wrapper_name} # return the class

```

EOS  
end  
end

class Person  
attr\_accessor :test  
PROPERTY\_DESCRIPTORS = { :int =\> [:test] }  
end

wrapper = WrapperGenerator.new  
wrapped = wrapper.wrap(Person.new)  
puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum  
wrapped.test = 35 # !!! Crashes here !!!  
puts “Assigned”  
puts wrapped.test, wrapped.test.inspect, wrapped.test.class

---

<div class="post-metadata">

**Author:** ![sickboy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/7ea924/32.png) [@sickboy](https://www.ruby-forum.com/u/sickboy)\
**Post date:** [June 14, 2011, 6:21pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301/2 "2011-06-14T18:21:02Z")

</div>

My guess would be that you’re not boxing the value.  
You need to emit OpCodes.Box to convert bool/int/… to an Object before  
calling Invoke in setter. The setter should also return Object (your’s  
is void). In getter you need to use OpCodes.Unbox before returning.  
I’d also recommend using Func\<\> delegate instead of your custom delegate  
types if possible.

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 8:38 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: [Ironruby-core] WPF Databinding with RubyObjects, continuation,  
dynamically create wrappers with strong typed properties

Hello,

I recently stumbled upon this awesome code:  
[http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html](http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html)  
It does exactly what I need; dynamically wrapping my RubyObject into a  
CLR class with CLR properties, except that it’s designed only for string  
properties.

I’ve adjusted the code to support a number of types, incl int, bool and  
float.

However the CLR crashes when-ever I assign a value to a non-string  
property, e.g float or int.  
“The runtime has encountered a fatal error. The address of the error was  
at 0x5935788d, on thread 0x1adc. The error code is 0xc0000005. This  
error may be a bug in the CLR or in the unsafe or non-verifiable  
portions of user code. Common sources of this bug include user  
marshaling errors for COM-interop or PInvoke, which may corrupt the  
stack.”

Any assistance would be deeply appreciated.

In essence, instead of using typeof(string) inside the  
TypeGenerator.Generate method, i use e.g; typeof(int) or typeof(float)  
This is my current code:

C#:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Reflection;  
using System.Reflection.Emit;

namespace GenerateType  
{  
public class TypeGenerator  
{  
public delegate object GetPropertyDelegate(string propertyName);  
public delegate object SetPropertyDelegate(string propertyName,  
object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)  
{  
AssemblyName asmName = new AssemblyName(“BindingTypes”);  
AssemblyBuilder asmBuilder =  
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);  
ModuleBuilder modBuilder =  
asmBuilder.DefineDynamicModule(“Types”);  
TypeBuilder typeBuilder = modBuilder.DefineType(className,  
TypeAttributes.Public |  
TypeAttributes.Class |  
TypeAttributes.AutoClass |  
TypeAttributes.AnsiClass |  
TypeAttributes.BeforeFieldInit |  
TypeAttributes.AutoLayout);

```
        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);  
FieldBuilder setFieldBuilder =  
typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)
        {
            type = null;
            switch (s)
            {
                case "float":
                    type = typeof(float);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "bool":
                    type = typeof(bool);
                    break;
                //case "dynamic":
                // type = dynamic;
            }
            if (type != null)
            {
                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);  
}  
}  
return typeBuilder.CreateType();  
}

```
    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)  
{  
foreach (string propertyName in properties)  
{  
PropertyBuilder propBuilder =  
typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type {});  
MethodBuilder getter = typeBuilder.DefineMethod(“get\_” +  
propertyName,  
getSetAttr,  
type,  
Type.EmptyTypes);

```
            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Ret);

```
            // Define the "set" accessor method for CustomerName.
            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,  
getSetAttr,  
null,  
new Type { type });

```
            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Pop);  
ilGen.Emit(OpCodes.Ret);

```
            // Last, we must map the two methods created above to 

```

our PropertyBuilder to  
// their corresponding behaviors, “get” and “set”  
respectively.  
propBuilder.SetGetMethod(getter);  
propBuilder.SetSetMethod(setter);  
}  
}  
}  
}

Ruby Code:

include System::Data  
include System::Windows::Data  
include System::ComponentModel

include GenerateType  
class WrapperGenerator  
def initialize  
@wrapper\_cache = {}  
end

def wrap(ruby\_object)  
if ruby\_object.is\_a? Array  
ruby\_object.map {|o| wrap(o) }  
else  
cache(ruby\_object) unless cached(ruby\_object)  
wrapper\_class = cached(ruby\_object)  
wrapper\_class.new(ruby\_object)  
end  
end

def invalidate  
@wrapper\_cache.clear  
end  
private  
def cached(object)  
@wrapper\_cache[object.class.name]  
end

def cache(object)  
@wrapper\_cache[object.class.name] = generate\_wrapper(object)  
end

def generate\_wrapper(object)  
wrapper\_name = “#{object.class.name}Wrapper”  
properties = Dictionary.of(System::String,  
List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)
  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|
    properties[k.to_clr_string] = List.of(System::String).new
    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}
  end
else
  # Default to String properties
  properties["string"] = List.of(System::String).new
  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}  
end

```
wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)  
base\_instance = System::Activator.create\_instance wrapper\_base\_type

```
eval <<EOS
  class #{wrapper_name} < base_instance.class
    def initialize(original)
      self.on_get = lambda do |prop|
        original.send prop
      end

      self.on_set = lambda do |prop, val|
        original.send "\#{prop}=", val
      end
    end
  end
  return #{wrapper_name} # return the class

```

EOS  
end  
end

class Person  
attr\_accessor :test  
PROPERTY\_DESCRIPTORS = { :int =\> [:test] }  
end

wrapper = WrapperGenerator.new  
wrapped = wrapper.wrap(Person.new)  
puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum  
wrapped.test = 35 # !!! Crashes here !!!  
puts “Assigned”  
puts wrapped.test, wrapped.test.inspect, wrapped.test.class

---

<div class="post-metadata">

**Author:** ![sickboy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/7ea924/32.png) [@sickboy](https://www.ruby-forum.com/u/sickboy)\
**Post date:** [June 14, 2011, 7:15pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301/3 "2011-06-14T19:15:23Z")

</div>

Thanks! Still new to .NET and especially this stuff.

The Box/Unbox seems to have worked, except that if I set e.g 35 as new  
value, when reading the value back, something completely different comes  
back, e.g; 150007660, but correct class Fixnum.  
This number seems randomized, and changes upon accessing the getter for  
the property more than once.

Any suggestions or alternatives welcome.  
My backup plan is to generate the C# classes from Ruby dynamically  
during development and saving them into a .cs file to be compiled with  
exe/dll.

Regards

From: Tomas M.  
Sent: Tuesday, June 14, 2011 6:05 PM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation,dynamically create wrappers with strong typed properties

My guess would be that you’re not boxing the value.

You need to emit OpCodes.Box to convert bool/int/… to an Object before  
calling Invoke in setter. The setter should also return Object (your’s  
is void). In getter you need to use OpCodes.Unbox before returning.

I’d also recommend using Func\<\> delegate instead of your custom delegate  
types if possible.

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 8:38 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: [Ironruby-core] WPF Databinding with RubyObjects, continuation,  
dynamically create wrappers with strong typed properties

Hello,

I recently stumbled upon this awesome code:  
[http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html](http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html)

It does exactly what I need; dynamically wrapping my RubyObject into a  
CLR class with CLR properties, except that it’s designed only for string  
properties.

I’ve adjusted the code to support a number of types, incl int, bool and  
float.

However the CLR crashes when-ever I assign a value to a non-string  
property, e.g float or int.

“The runtime has encountered a fatal error. The address of the error was  
at 0x5935788d, on thread 0x1adc. The error code is 0xc0000005. This  
error may be a bug in the CLR or in the unsafe or non-verifiable  
portions of user code. Common sources of this bug include user  
marshaling errors for COM-interop or PInvoke, which may corrupt the  
stack.”

Any assistance would be deeply appreciated.

In essence, instead of using typeof(string) inside the  
TypeGenerator.Generate method, i use e.g; typeof(int) or typeof(float)

This is my current code:

C#:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

using System.Reflection.Emit;

namespace GenerateType

{

```
public class TypeGenerator

{

    public delegate object GetPropertyDelegate(string propertyName);

    public delegate object SetPropertyDelegate(string propertyName, 

```

object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)

```
    {

        AssemblyName asmName = new AssemblyName("BindingTypes");

        AssemblyBuilder asmBuilder = 

```

AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);

```
        ModuleBuilder modBuilder = 

```

asmBuilder.DefineDynamicModule(“Types”);

```
        TypeBuilder typeBuilder = modBuilder.DefineType(className,

                    TypeAttributes.Public |

                    TypeAttributes.Class |

                    TypeAttributes.AutoClass |

                    TypeAttributes.AnsiClass |

                    TypeAttributes.BeforeFieldInit |

                    TypeAttributes.AutoLayout);

        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);

```
        FieldBuilder setFieldBuilder = 

```

typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)

        {

            type = null;

            switch (s)

            {

                case "float":

                    type = typeof(float);

                    break;

                case "int":

                    type = typeof(int);

                    break;

                case "string":

                    type = typeof(string);

                    break;

                case "bool":

                    type = typeof(bool);

                    break;

                //case "dynamic":

                // type = dynamic;

            }

            if (type != null)

            {

                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);

```
            }

        }

        return typeBuilder.CreateType();

    }

    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)

```
    {

        foreach (string propertyName in properties)

        {

            PropertyBuilder propBuilder = 

```

typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type {});

```
            MethodBuilder getter = typeBuilder.DefineMethod("get_" + 

```

propertyName,

```
                               getSetAttr,

                               type,

                               Type.EmptyTypes);

            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);

            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);

            ilGen.Emit(OpCodes.Ldstr, propertyName);

            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));

```
            ilGen.Emit(OpCodes.Ret);

            // Define the "set" accessor method for CustomerName.

            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,

```
                                           getSetAttr,

                                           null,

                                           new Type[] { type });

            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);

            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);

            ilGen.Emit(OpCodes.Ldstr, propertyName);

            ilGen.Emit(OpCodes.Ldarg_1);

            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));

```
            ilGen.Emit(OpCodes.Pop);

            ilGen.Emit(OpCodes.Ret);

            // Last, we must map the two methods created above to 

```

our PropertyBuilder to

```
            // their corresponding behaviors, "get" and "set" 

```

respectively.

```
            propBuilder.SetGetMethod(getter);

            propBuilder.SetSetMethod(setter);

        }

    }

}

```

}

Ruby Code:

include System::Data

include System::Windows::Data

include System::ComponentModel

include GenerateType

class WrapperGenerator

def initialize

```
@wrapper_cache = {}

```

end

def wrap(ruby\_object)

```
if ruby_object.is_a? Array

  ruby_object.map {|o| wrap(o) }

else

  cache(ruby_object) unless cached(ruby_object)

  wrapper_class = cached(ruby_object)

  wrapper_class.new(ruby_object)

end

```

end

def invalidate

```
@wrapper_cache.clear

```

end

private

def cached(object)

```
@wrapper_cache[object.class.name]

```

end

def cache(object)

```
@wrapper_cache[object.class.name] = generate_wrapper(object)

```

end

def generate\_wrapper(object)

```
wrapper_name = "#{object.class.name}Wrapper"

properties = Dictionary.of(System::String, 

```

List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)

  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|

    properties[k.to_clr_string] = List.of(System::String).new

    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}

  end

else

  # Default to String properties

  properties["string"] = List.of(System::String).new

  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}

```
end

wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)

```
base_instance = System::Activator.create_instance wrapper_base_type

eval <<EOS

  class #{wrapper_name} < base_instance.class

    def initialize(original)

      self.on_get = lambda do |prop|

        original.send prop

      end

      self.on_set = lambda do |prop, val|

        original.send "\#{prop}=", val

      end

    end

  end

  return #{wrapper_name} # return the class

```

EOS

end

end

class Person

attr\_accessor :test

PROPERTY\_DESCRIPTORS = { :int =\> [:test] }

end

wrapper = WrapperGenerator.new

wrapped = wrapper.wrap(Person.new)

puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum

wrapped.test = 35 # !!! Crashes here !!!

puts “Assigned”

puts wrapped.test, wrapped.test.inspect, wrapped.test.class

---

<div class="post-metadata">

**Author:** ![sickboy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/7ea924/32.png) [@sickboy](https://www.ruby-forum.com/u/sickboy)\
**Post date:** [June 14, 2011, 7:50pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301/4 "2011-06-14T19:50:38Z")

</div>

Your backup plan might actually be better – emitting code at runtime is  
definitely slower than loading already compiled code.

You’re still emitting some wrong instructions. Can you send your new  
code?

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 10:03 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation, dynamically create wrappers with strong typed properties

Thanks! Still new to .NET and especially this stuff.

The Box/Unbox seems to have worked, except that if I set e.g 35 as new  
value, when reading the value back, something completely different comes  
back, e.g; 150007660, but correct class Fixnum.  
This number seems randomized, and changes upon accessing the getter for  
the property more than once.

Any suggestions or alternatives welcome.  
My backup plan is to generate the C# classes from Ruby dynamically  
during development and saving them into a .cs file to be compiled with  
exe/dll.

Regards

From: Tomas M.[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Sent: Tuesday, June 14, 2011 6:05 PM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation,dynamically create wrappers with strong typed properties

My guess would be that you’re not boxing the value.  
You need to emit OpCodes.Box to convert bool/int/… to an Object before  
calling Invoke in setter. The setter should also return Object (your’s  
is void). In getter you need to use OpCodes.Unbox before returning.  
I’d also recommend using Func\<\> delegate instead of your custom delegate  
types if possible.

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 8:38 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: [Ironruby-core] WPF Databinding with RubyObjects, continuation,  
dynamically create wrappers with strong typed properties

Hello,

I recently stumbled upon this awesome code:  
[http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html](http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html)  
It does exactly what I need; dynamically wrapping my RubyObject into a  
CLR class with CLR properties, except that it’s designed only for string  
properties.

I’ve adjusted the code to support a number of types, incl int, bool and  
float.

However the CLR crashes when-ever I assign a value to a non-string  
property, e.g float or int.  
“The runtime has encountered a fatal error. The address of the error was  
at 0x5935788d, on thread 0x1adc. The error code is 0xc0000005. This  
error may be a bug in the CLR or in the unsafe or non-verifiable  
portions of user code. Common sources of this bug include user  
marshaling errors for COM-interop or PInvoke, which may corrupt the  
stack.”

Any assistance would be deeply appreciated.

In essence, instead of using typeof(string) inside the  
TypeGenerator.Generate method, i use e.g; typeof(int) or typeof(float)  
This is my current code:

C#:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Reflection;  
using System.Reflection.Emit;

namespace GenerateType  
{  
public class TypeGenerator  
{  
public delegate object GetPropertyDelegate(string propertyName);  
public delegate object SetPropertyDelegate(string propertyName,  
object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)  
{  
AssemblyName asmName = new AssemblyName(“BindingTypes”);  
AssemblyBuilder asmBuilder =  
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);  
ModuleBuilder modBuilder =  
asmBuilder.DefineDynamicModule(“Types”);  
TypeBuilder typeBuilder = modBuilder.DefineType(className,  
TypeAttributes.Public |  
TypeAttributes.Class |  
TypeAttributes.AutoClass |  
TypeAttributes.AnsiClass |  
TypeAttributes.BeforeFieldInit |  
TypeAttributes.AutoLayout);

```
        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);  
FieldBuilder setFieldBuilder =  
typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)
        {
            type = null;
            switch (s)
            {
                case "float":
                    type = typeof(float);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "bool":
                    type = typeof(bool);
                    break;
                //case "dynamic":
                // type = dynamic;
            }
            if (type != null)
            {
                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);  
}  
}  
return typeBuilder.CreateType();  
}

```
    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)  
{  
foreach (string propertyName in properties)  
{  
PropertyBuilder propBuilder =  
typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type {});  
MethodBuilder getter = typeBuilder.DefineMethod(“get\_” +  
propertyName,  
getSetAttr,  
type,  
Type.EmptyTypes);

```
            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Ret);

```
            // Define the "set" accessor method for CustomerName.
            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,  
getSetAttr,  
null,  
new Type { type });

```
            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Pop);  
ilGen.Emit(OpCodes.Ret);

```
            // Last, we must map the two methods created above to 

```

our PropertyBuilder to  
// their corresponding behaviors, “get” and “set”  
respectively.  
propBuilder.SetGetMethod(getter);  
propBuilder.SetSetMethod(setter);  
}  
}  
}  
}

Ruby Code:

include System::Data  
include System::Windows::Data  
include System::ComponentModel

include GenerateType  
class WrapperGenerator  
def initialize  
@wrapper\_cache = {}  
end

def wrap(ruby\_object)  
if ruby\_object.is\_a? Array  
ruby\_object.map {|o| wrap(o) }  
else  
cache(ruby\_object) unless cached(ruby\_object)  
wrapper\_class = cached(ruby\_object)  
wrapper\_class.new(ruby\_object)  
end  
end

def invalidate  
@wrapper\_cache.clear  
end  
private  
def cached(object)  
@wrapper\_cache[object.class.name]  
end

def cache(object)  
@wrapper\_cache[object.class.name] = generate\_wrapper(object)  
end

def generate\_wrapper(object)  
wrapper\_name = “#{object.class.name}Wrapper”  
properties = Dictionary.of(System::String,  
List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)
  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|
    properties[k.to_clr_string] = List.of(System::String).new
    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}
  end
else
  # Default to String properties
  properties["string"] = List.of(System::String).new
  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}  
end

```
wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)  
base\_instance = System::Activator.create\_instance wrapper\_base\_type

```
eval <<EOS
  class #{wrapper_name} < base_instance.class
    def initialize(original)
      self.on_get = lambda do |prop|
        original.send prop
      end

      self.on_set = lambda do |prop, val|
        original.send "\#{prop}=", val
      end
    end
  end
  return #{wrapper_name} # return the class

```

EOS  
end  
end

class Person  
attr\_accessor :test  
PROPERTY\_DESCRIPTORS = { :int =\> [:test] }  
end

wrapper = WrapperGenerator.new  
wrapped = wrapper.wrap(Person.new)  
puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum  
wrapped.test = 35 # !!! Crashes here !!!  
puts “Assigned”  
puts wrapped.test, wrapped.test.inspect, wrapped.test.class

---

<div class="post-metadata">

**Author:** ![sickboy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/7ea924/32.png) [@sickboy](https://www.ruby-forum.com/u/sickboy)\
**Post date:** [June 14, 2011, 8:00pm UTC](https://www.ruby-forum.com/t/wpf-databinding-with-rubyobjects-continuation-dynamically-create-wrappers-with-strong-typed-proper/208301/5 "2011-06-14T20:00:33Z")

</div>

Thanks! Currently on my way with the backup plan.

But here’s the C# and Ruby for the dynamic implementation:

C#

namespace GenerateType  
{  
public class TypeGenerator  
{  
public delegate object GetPropertyDelegate(string propertyName);  
public delegate object SetPropertyDelegate(string propertyName,  
object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)  
{  
AssemblyName asmName = new AssemblyName(“BindingTypes”);  
AssemblyBuilder asmBuilder =  
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);  
ModuleBuilder modBuilder =  
asmBuilder.DefineDynamicModule(“Types”);  
TypeBuilder typeBuilder = modBuilder.DefineType(className,  
TypeAttributes.Public |  
TypeAttributes.Class |  
TypeAttributes.AutoClass |  
TypeAttributes.AnsiClass |  
TypeAttributes.BeforeFieldInit |  
TypeAttributes.AutoLayout);

```
        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);  
FieldBuilder setFieldBuilder =  
typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)
        {
            type = null;
            switch (s)
            {
                case "float":
                    type = typeof(float);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "bool":
                    type = typeof(bool);
                    break;
                //case "dynamic":
                // type = dynamic;
            }
            if (type != null)
            {
                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);  
}  
}  
return typeBuilder.CreateType();  
}

```
    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)  
{  
foreach (string propertyName in properties)  
{  
PropertyBuilder propBuilder =  
typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type {});  
MethodBuilder getter = typeBuilder.DefineMethod(“get\_” +  
propertyName,  
getSetAttr,  
type,  
Type.EmptyTypes);

```
            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));  
if (type != typeof(string))  
{  
[//ilGen.Emit](https://ilGen.Emit)(OpCodes.Unbox, type);  
}  
ilGen.Emit(OpCodes.Ret);

```
            // Define the "set" accessor method for CustomerName.
            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,  
getSetAttr,  
null,  
new Type { type });

```
            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);
            ilGen.Emit(OpCodes.Ldstr, propertyName);
            ilGen.Emit(OpCodes.Ldarg_1);
            if (type == typeof(int) || type == typeof(float))
            {
                ilGen.Emit(OpCodes.Box, type);
            }
            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));  
ilGen.Emit(OpCodes.Pop);  
ilGen.Emit(OpCodes.Ret);

```
            // Last, we must map the two methods created above to 

```

our PropertyBuilder to  
// their corresponding behaviors, “get” and “set”  
respectively.  
propBuilder.SetGetMethod(getter);  
propBuilder.SetSetMethod(setter);  
}  
}  
}  
}

Ruby:

include System::Data  
include System::Windows::Data  
include System::ComponentModel

include GenerateType  
class WrapperGenerator  
def initialize  
@wrapper\_cache = {}  
end

def wrap(ruby\_object)  
if ruby\_object.is\_a? Array  
ruby\_object.map {|o| wrap(o) }  
else  
cache(ruby\_object) unless cached(ruby\_object)  
wrapper\_class = cached(ruby\_object)  
wrapper\_class.new(ruby\_object)  
end  
end

def invalidate  
@wrapper\_cache.clear  
end  
private  
def cached(object)  
@wrapper\_cache[object.class.name]  
end

def cache(object)  
@wrapper\_cache[object.class.name] = generate\_wrapper(object)  
end

def generate\_wrapper(object)  
wrapper\_name = “#{object.class.name}Wrapper”  
properties = Dictionary.of(System::String,  
List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)
  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|
    properties[k.to_clr_string] = List.of(System::String).new
    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}
  end
else
  # Default to String properties
  properties["string"] = List.of(System::String).new
  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}  
end

```
wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)  
base\_instance = System::Activator.create\_instance wrapper\_base\_type

```
eval <<EOS
  class #{wrapper_name} < base_instance.class
    def initialize(original)
      self.on_get = lambda do |prop|
        original.send prop
      end

      self.on_set = lambda do |prop, val|
        original.send "\#{prop}=", val
      end
    end
  end
  return #{wrapper_name} # return the class

```

EOS  
end  
end

class Person  
attr\_accessor :test  
PROPERTY\_DESCRIPTORS = { :int =\> [:test] }  
end

wrapper = WrapperGenerator.new  
wrapped = wrapper.wrap(Person.new)  
puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum  
wrapped.test = System::Int16.new(35) # !!! Crashes here !!!  
puts “Assigned”  
puts wrapped.test, wrapped.test.inspect, wrapped.test.class

From: Tomas M.  
Sent: Tuesday, June 14, 2011 7:49 PM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation,dynamically create wrappers with strong typed properties

Your backup plan might actually be better – emitting code at runtime is  
definitely slower than loading already compiled code.

You’re still emitting some wrong instructions. Can you send your new  
code?

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 10:03 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation, dynamically create wrappers with strong typed properties

Thanks! Still new to .NET and especially this stuff.

The Box/Unbox seems to have worked, except that if I set e.g 35 as new  
value, when reading the value back, something completely different comes  
back, e.g; 150007660, but correct class Fixnum.

This number seems randomized, and changes upon accessing the getter for  
the property more than once.

Any suggestions or alternatives welcome.

My backup plan is to generate the C# classes from Ruby dynamically  
during development and saving them into a .cs file to be compiled with  
exe/dll.

Regards

From: Tomas M.

Sent: Tuesday, June 14, 2011 6:05 PM

To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

Subject: Re: [Ironruby-core] WPF Databinding with RubyObjects,  
continuation,dynamically create wrappers with strong typed properties

My guess would be that you’re not boxing the value.

You need to emit OpCodes.Box to convert bool/int/… to an Object before  
calling Invoke in setter. The setter should also return Object (your’s  
is void). In getter you need to use OpCodes.Unbox before returning.

I’d also recommend using Func\<\> delegate instead of your custom delegate  
types if possible.

Tomas

From: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Sickboy  
Sent: Tuesday, June 14, 2011 8:38 AM  
To: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: [Ironruby-core] WPF Databinding with RubyObjects, continuation,  
dynamically create wrappers with strong typed properties

Hello,

I recently stumbled upon this awesome code:  
[http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html](http://rubyforge.org/pipermail/ironruby-core/2008-December/003377.html)

It does exactly what I need; dynamically wrapping my RubyObject into a  
CLR class with CLR properties, except that it’s designed only for string  
properties.

I’ve adjusted the code to support a number of types, incl int, bool and  
float.

However the CLR crashes when-ever I assign a value to a non-string  
property, e.g float or int.

“The runtime has encountered a fatal error. The address of the error was  
at 0x5935788d, on thread 0x1adc. The error code is 0xc0000005. This  
error may be a bug in the CLR or in the unsafe or non-verifiable  
portions of user code. Common sources of this bug include user  
marshaling errors for COM-interop or PInvoke, which may corrupt the  
stack.”

Any assistance would be deeply appreciated.

In essence, instead of using typeof(string) inside the  
TypeGenerator.Generate method, i use e.g; typeof(int) or typeof(float)

This is my current code:

C#:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

using System.Reflection.Emit;

namespace GenerateType

{

```
public class TypeGenerator

{

    public delegate object GetPropertyDelegate(string propertyName);

    public delegate object SetPropertyDelegate(string propertyName, 

```

object value);

```
    public static Type Generate(string className, Dictionary<string, 

```

List\> properties)

```
    {

        AssemblyName asmName = new AssemblyName("BindingTypes");

        AssemblyBuilder asmBuilder = 

```

AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,  
AssemblyBuilderAccess.Run);

```
        ModuleBuilder modBuilder = 

```

asmBuilder.DefineDynamicModule(“Types”);

```
        TypeBuilder typeBuilder = modBuilder.DefineType(className,

                    TypeAttributes.Public |

                    TypeAttributes.Class |

                    TypeAttributes.AutoClass |

                    TypeAttributes.AnsiClass |

                    TypeAttributes.BeforeFieldInit |

                    TypeAttributes.AutoLayout);

        FieldBuilder getFieldBuilder = 

```

typeBuilder.DefineField(“OnGet”, typeof(GetPropertyDelegate),  
FieldAttributes.Public);

```
        FieldBuilder setFieldBuilder = 

```

typeBuilder.DefineField(“OnSet”, typeof(SetPropertyDelegate),  
FieldAttributes.Public);

```
        MethodAttributes getSetAttr = MethodAttributes.Public | 

```

MethodAttributes.SpecialName | MethodAttributes.HideBySig;

```
        Type type = null;

        foreach (string s in properties.Keys)

        {

            type = null;

            switch (s)

            {

                case "float":

                    type = typeof(float);

                    break;

                case "int":

                    type = typeof(int);

                    break;

                case "string":

                    type = typeof(string);

                    break;

                case "bool":

                    type = typeof(bool);

                    break;

                //case "dynamic":

                // type = dynamic;

            }

            if (type != null)

            {

                GenerateProperties(properties[s], type, typeBuilder, 

```

getSetAttr, getFieldBuilder, setFieldBuilder);

```
            }

        }

        return typeBuilder.CreateType();

    }

    public static void GenerateProperties(List<string> properties, 

```

Type type, TypeBuilder typeBuilder, MethodAttributes getSetAttr,  
FieldBuilder getFieldBuilder, FieldBuilder setFieldBuilder)

```
    {

        foreach (string propertyName in properties)

        {

            PropertyBuilder propBuilder = 

```

typeBuilder.DefineProperty(propertyName, PropertyAttributes.None,  
typeof(object), new Type {});

```
            MethodBuilder getter = typeBuilder.DefineMethod("get_" + 

```

propertyName,

```
                               getSetAttr,

                               type,

                               Type.EmptyTypes);

            ILGenerator ilGen = getter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);

            ilGen.Emit(OpCodes.Ldfld, getFieldBuilder);

            ilGen.Emit(OpCodes.Ldstr, propertyName);

            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(GetPropertyDelegate).GetMethod(“Invoke”));

```
            ilGen.Emit(OpCodes.Ret);

            // Define the "set" accessor method for CustomerName.

            MethodBuilder setter = typeBuilder.DefineMethod("set_" + 

```

propertyName,

```
                                           getSetAttr,

                                           null,

                                           new Type[] { type });

            ilGen = setter.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);

            ilGen.Emit(OpCodes.Ldfld, setFieldBuilder);

            ilGen.Emit(OpCodes.Ldstr, propertyName);

            ilGen.Emit(OpCodes.Ldarg_1);

            ilGen.Emit(OpCodes.Callvirt, 

```

typeof(SetPropertyDelegate).GetMethod(“Invoke”));

```
            ilGen.Emit(OpCodes.Pop);

            ilGen.Emit(OpCodes.Ret);

            // Last, we must map the two methods created above to 

```

our PropertyBuilder to

```
            // their corresponding behaviors, "get" and "set" 

```

respectively.

```
            propBuilder.SetGetMethod(getter);

            propBuilder.SetSetMethod(setter);

        }

    }

}

```

}

Ruby Code:

include System::Data

include System::Windows::Data

include System::ComponentModel

include GenerateType

class WrapperGenerator

def initialize

```
@wrapper_cache = {}

```

end

def wrap(ruby\_object)

```
if ruby_object.is_a? Array

  ruby_object.map {|o| wrap(o) }

else

  cache(ruby_object) unless cached(ruby_object)

  wrapper_class = cached(ruby_object)

  wrapper_class.new(ruby_object)

end

```

end

def invalidate

```
@wrapper_cache.clear

```

end

private

def cached(object)

```
@wrapper_cache[object.class.name]

```

end

def cache(object)

```
@wrapper_cache[object.class.name] = generate_wrapper(object)

```

end

def generate\_wrapper(object)

```
wrapper_name = "#{object.class.name}Wrapper"

properties = Dictionary.of(System::String, 

```

List.of(System::String)).new

```
if defined?(object.class::PROPERTY_DESCRIPTORS)

  object.class::PROPERTY_DESCRIPTORS.each_pair do |k, v|

    properties[k.to_clr_string] = List.of(System::String).new

    properties[k.to_clr_string].replace v.map{|e| e.to_clr_string}

  end

else

  # Default to String properties

  properties["string"] = List.of(System::String).new

  properties["string"].replace (object.methods - 

```

Object.instance\_methods).map{|e| e.to\_clr\_string}

```
end

wrapper_base_type = TypeGenerator.generate("#{wrapper_name}Base", 

```

properties)

```
base_instance = System::Activator.create_instance wrapper_base_type

eval <<EOS

  class #{wrapper_name} < base_instance.class

    def initialize(original)

      self.on_get = lambda do |prop|

        original.send prop

      end

      self.on_set = lambda do |prop, val|

        original.send "\#{prop}=", val

      end

    end

  end

  return #{wrapper_name} # return the class

```

EOS

end

end

class Person

attr\_accessor :test

PROPERTY\_DESCRIPTORS = { :int =\> [:test] }

end

wrapper = WrapperGenerator.new

wrapped = wrapper.wrap(Person.new)

puts “Wrapped”

# wrapped.test = “35” # properly generates Exception: Cannot convert

String to Fixnum

wrapped.test = 35 # !!! Crashes here !!!

puts “Assigned”

puts wrapped.test, wrapped.test.inspect, wrapped.test.class

* * *

* * *

Ironruby-core mailing list  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[http://rubyforge.org/mailman/listinfo/ironruby-core](http://rubyforge.org/mailman/listinfo/ironruby-core)
