<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.6001.18157" name=GENERATOR></HEAD>
<BODY>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2>Great work Joshua!</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2></FONT></SPAN>&nbsp;</DIV>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2>IronRuby-objects don't work in many parts of 
dotnet-framework because they are instances of Ruby-classes that are 
<EM><STRONG>not </STRONG></EM>dotnet-classes. Another example that has causes 
headache to me is XAML where names of user-defined classes can be used as 
elements but they must be user-defined <STRONG><EM>dotnet</EM></STRONG>-classes 
(not Ruby).</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2></FONT></SPAN>&nbsp;</DIV>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2>I suppose and hope that with the support for dynamic 
languages increasing in dotnet 4 / C# 4, there will be more built-in support for 
this (it would be really nice to use dynamic types as 
XAML-elements...)</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=996172612-12122008><FONT face=Arial 
color=#0000ff size=2>
<DIV align=left><B><FONT size=2>
<P>Robert Brotherus<BR></B>Software architect<BR><B>Napa 
Ltd<BR></B>Tammasaarenkatu 3, Helsinki FI-00180<BR>P.O.Box 470, Helsinki 
FI-00181<BR><BR>Tel. +358 9 22 813 1 <BR>Direct. +358 9 22 813 611 <BR>GSM +358 
45 11&nbsp;456 02 <BR>Fax. +358 9 22 813 800 <BR><BR>Email: </FONT><A 
href="mailto:Robert.Brotherus@napa.fi"><U><FONT color=#0000ff 
size=2>Robert.Brotherus@napa.fi</U></FONT></A><FONT size=2> <BR></FONT><A 
href="http://www.napa.fi/"><U><FONT color=#0000ff 
size=2>www.napa.fi</U></FONT></A><FONT size=2> 
<BR></P></FONT></DIV></FONT></SPAN></DIV><BR>
<DIV class=OutlookMessageHeader lang=en-us dir=ltr align=left>
<HR tabIndex=-1>
<FONT face=Tahoma size=2><B>From:</B> ironruby-core-bounces@rubyforge.org 
[mailto:ironruby-core-bounces@rubyforge.org] <B>On Behalf Of </B>Joshua 
Nussbaum<BR><B>Sent:</B> Friday, December 12, 2008 8:56 AM<BR><B>To:</B> 
ironruby-core@rubyforge.org<BR><B>Subject:</B> [Ironruby-core] WPF databinding 
with ruby objects. Workaround :)<BR></FONT><BR></DIV>
<DIV></DIV>Hey yall<BR><BR>Seems IronRuby objects do not yet work with WPF 
databinding. One approach to a workaround is to emit a wrapper type that defines 
CLR properties. When WPF calls the getter/setter the call is forwarded ot the 
contained contained ruby object. This will allow defining business objects in 
ruby and databing them to the UI. <BR><BR>This might be useful to thers, so here 
is my approach. The first part is C# code that defines a type given a list of 
property names. The second part is ruby code that creates a wrapper instance for 
a given ruby object and caches the type so that you dont generate a type for 
each element in an array..<BR><BR>The C# code to generate a type:<BR><BR>using 
System;<BR>using System.Collections.Generic;<BR>using System.Linq;<BR>using 
System.Text;<BR>using System.Reflection;<BR>using 
System.Reflection.Emit;<BR><BR>namespace 
GenerateType<BR>{<BR><BR>&nbsp;&nbsp;&nbsp; public class 
TypeGenerator<BR>&nbsp;&nbsp;&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate object 
GetPropertyDelegate(string 
propertyName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate 
object SetPropertyDelegate(string propertyName, object 
value);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static Type 
Generate(string className, List&lt;string&gt; 
properties)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
AssemblyName asmName = new 
AssemblyName("BindingTypes");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.
<DIV class="ArwC7c ckChnd" id=:11m>DefineDynamicAssembly(asmName, 
AssemblyBuilderAccess.Run);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ModuleBuilder modBuilder = 
asmBuilder.DefineDynamicModule("Types");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeBuilder typeBuilder = 
modBuilder.DefineType(className,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.Public 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.Class 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.AutoClass 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.AnsiClass 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.BeforeFieldInit 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
TypeAttributes.AutoLayout);<BR><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
FieldBuilder getFieldBuilder = typeBuilder.DefineField("OnGet", 
typeof(GetPropertyDelegate), 
FieldAttributes.Public);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
FieldBuilder setFieldBuilder = typeBuilder.DefineField("OnSet", 
typeof(SetPropertyDelegate), 
FieldAttributes.Public);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
MethodAttributes getSetAttr 
=<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
MethodAttributes.Public | MethodAttributes.SpecialName 
|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
MethodAttributes.HideBySig;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
foreach (string propertyName in 
properties)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
PropertyBuilder propBuilder = typeBuilder.DefineProperty(propertyName, 
PropertyAttributes.None, typeof(object), new Type[] 
{});<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
MethodBuilder getter 
=<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
typeBuilder.DefineMethod("get_" + 
propertyName,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
getSetAttr,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
typeof(string),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Type.EmptyTypes);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ILGenerator ilGen = 
getter.GetILGenerator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldarg_0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldfld, 
getFieldBuilder);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldstr, 
propertyName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Callvirt, 
typeof(GetPropertyDelegate).GetMethod("Invoke"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ret);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// Define the "set" accessor method for 
CustomerName.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
MethodBuilder setter 
=<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
typeBuilder.DefineMethod("set_" + 
propertyName,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
getSetAttr,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
null,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
new Type[] { typeof(string) 
});<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen = 
setter.GetILGenerator();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldarg_0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldfld, 
setFieldBuilder);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldstr, 
propertyName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ldarg_1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Callvirt, 
typeof(SetPropertyDelegate).GetMethod("Invoke"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Pop);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ilGen.Emit(OpCodes.Ret);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// Last, we must map the two methods created above to our PropertyBuilder to 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// their corresponding behaviors, "get" and "set" respectively. 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
propBuilder.SetGetMethod(getter);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
propBuilder.SetSetMethod(setter);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
return 
typeBuilder.CreateType();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 
}<BR>}<BR><BR><BR>And here is the ruby code to generate the wrapper 
type<BR><BR>require 'mscorlib'<BR>require 'C:\Documents and Settings\Josh\My 
Documents\Visual Studio 
2008\Projects\GenerateType\GenerateType\bin\Release\GenerateType.dll'<BR>require 
'PresentationFramework, Version=<A href="http://3.0.0.0/" 
target=_blank>3.0.0.0</A>,Culture=neutral, 
PublicKeyToken=31bf3856ad364e35'<BR>require 'PresentationCore, Version=<A 
href="http://3.0.0.0/" target=_blank>3.0.0.0</A>, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35'<BR>require 'WindowsBase, Version=<A 
href="http://3.0.0.0/" target=_blank>3.0.0.0</A>, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35'<BR><BR>include System<BR>include 
System::Collections::Generic<BR>include GenerateType<BR>include 
System::Collections::ObjectModel<BR>include System::Windows<BR>include 
System::Windows::Controls<BR>include System::Windows::Data<BR>include 
System::Windows::Input<BR><BR>class WrapperGenerator<BR>&nbsp; def 
initialize<BR>&nbsp;&nbsp;&nbsp; @wrapper_cache = {}<BR>&nbsp; end<BR><BR>&nbsp; 
def wrap(ruby_object)<BR>&nbsp;&nbsp;&nbsp; if ruby_object.is_a? 
Array<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ruby_object.map {|o| wrap(o) 
}<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
cache(ruby_object) unless cached(ruby_object)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
wrapper_class = cached(ruby_object)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
wrapper_class.new(ruby_object)<BR>&nbsp;&nbsp;&nbsp; end<BR>&nbsp; 
end<BR><BR>&nbsp; def invalidate<BR>&nbsp;&nbsp;&nbsp; 
@wrapper_cache.clear<BR>&nbsp; end<BR>private<BR>&nbsp; def 
cached(object)<BR>&nbsp;&nbsp;&nbsp; @wrapper_cache[<A 
href="http://object.class.name/" target=_blank>object.class.name</A>]<BR>&nbsp; 
end<BR>&nbsp; <BR>&nbsp; def cache(object)<BR>&nbsp;&nbsp;&nbsp; 
@wrapper_cache[<A href="http://object.class.name/" 
target=_blank>object.class.name</A>] = generate_wrapper(object)<BR>&nbsp; 
end<BR><BR>&nbsp; def generate_wrapper(object)<BR>&nbsp;&nbsp;&nbsp; 
wrapper_name = "#{<A href="http://object.class.name/" 
target=_blank>object.class.name</A>}Wrapper"<BR>&nbsp;&nbsp;&nbsp; properties = 
List.of(System::String).new<BR><BR>&nbsp;&nbsp;&nbsp; (object.methods - 
Object.instance_methods).each {|m| properties.add 
m.to_s}<BR><BR>&nbsp;&nbsp;&nbsp; wrapper_base_type = 
TypeGenerator.generate("#{wrapper_name}Base", properties)<BR>&nbsp;&nbsp;&nbsp; 
base_instance = Activator.create_instance 
wrapper_base_type<BR><BR>&nbsp;&nbsp;&nbsp; eval 
&lt;&lt;EOS<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class #{wrapper_name} &lt; 
base_instance.class<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def 
initialize(original)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
self.on_get = lambda do 
|prop|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
original.send prop<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
end<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.on_set = 
lambda do |prop, 
val|<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
original.send "\#{prop}=", 
val<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
end<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
end<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
return #{wrapper_name} # return the class<BR>EOS<BR>&nbsp;&nbsp;&nbsp; 
<BR>&nbsp; end<BR>end<BR><BR>class Person <BR>&nbsp; attr_accessor :first_name, 
:last_name<BR><BR>&nbsp; def initialize(first_name, 
last_name)<BR>&nbsp;&nbsp;&nbsp; @first_name, @last_name = first_name, 
last_name<BR>&nbsp; end<BR><BR>&nbsp; def full_name<BR>&nbsp;&nbsp;&nbsp; 
"#{last_name}, #{first_name}"<BR>&nbsp; end<BR>end<BR><BR><BR># A sample 
UI<BR><BR>people = []<BR><BR>10.times { |n| people &lt;&lt; Person.new("John 
#{n}", "Smith") }<BR><BR>wrapper = WrapperGenerator.new<BR><BR>w = 
Window.new<BR>combo = ComboBox.new<BR>combo.items_source = wrapper.wrap(people) 
# wrap people objects<BR>combo.display_member_path = "full_name"<BR>combo.margin 
= 20<BR>w.content = combo<BR><BR>Application.new.run w</DIV></BODY></HTML>