[Ironruby-core] interop question

Curt Hagenlocher curth at microsoft.com
Tue May 12 10:49:50 EDT 2009


We can’t apply all Ruby standards when we travel back to staticland.

When you define and use a Ruby class, we need to create a static CLR type to represent that class. This underlying type is constrained by what can be done with CLR types; and in particular, it’s structure is immutable. So we can’t just go back to this type and tell it that it should now implement IWeapon – we need to have known this at the time the class is created.

Now, it’s possible to be pretty flexible about the ingredients that go into the type. So if the IronRuby community decides to change how this underlying type is created – perhaps by taking additional metadata into account – then that’s no problem. But as soon as you create the first instance of ShurikenProxy, that’s when we need to freeze things and actually emit the type.

In this particular case, when creating a proxy for an object that implements certain CLR interfaces, the proxy itself will have to implement the same interfaces if the object is going to be passed back to static code. But Ruby’s metaprogramming makes this pretty easy – get all ancestors of class Module whose to_clr_type is not nil, and simply include those into a newly-created proxy class programmatically.


From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Ivan Porto Carrero
Sent: Tuesday, May 12, 2009 12:23 AM
To: ironruby-core
Subject: [Ironruby-core] interop question


Let's say I have these interfaces

public interface IWeapon{
        void Attack(IWarrior warrior);
        int Damage();
    }

    public interface IWarrior
    {

        int Id { get; }
        string Name { get; set; }
        bool IsKilledBy(IWeapon weapon);
        void Attack(IWarrior target, IWeapon weapon);
    }

And one implementor defined in C#

public class Ninja : IWarrior{

        private readonly int _id;

        public string Name { get; set; }
        public int Id { get { return _id; } }

        public void Attack(IWarrior target, IWeapon weapon){
            weapon.Attack(target);
        }

        public bool IsKilledBy(IWeapon weapon)
        {
            return weapon.Damage() > 3;
        }
    }

Now if I create an implementation of IWeapon in Ruby

class Shuriken

   include IWeapon

   def damage
      2
   end
end

which I then proceed to wrap in a forwarding class

class ShurikenProxy

  instance_methods.each do |name|
      undef_method name unless name =~ /^__|^instance_eval$/
    end

   def initialize
      @subject = Shuriken.new
   end

  def method_missing(m, *a, &b)
     @subject.send(m, *a, &b)
  end

end

Then I would expect this to work:

ninja = Ninja.new
ninja.is_killed_by ShurikenProxy.new

only it tells me that the ruby object isn't an implementation of IWeapon
while by all ruby standards it is. if you ask it for its ancestors it's got IWeapon there
if you ask it for its class it tells you Shuriken and not ShurikenProxy

Is that supposed to happen?


---
Met vriendelijke groeten - Best regards - Salutations
Ivan Porto Carrero
Blog: http://flanders.co.nz
Twitter: http://twitter.com/casualjim
Author of IronRuby in Action (http://manning.com/carrero)

Emma Goldman<http://www.brainyquote.com/quotes/authors/e/emma_goldman.html>  - "If voting changed anything, they'd make it illegal."
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20090512/621482fb/attachment.html>


More information about the Ironruby-core mailing list