Forum: IronRuby interop question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ivan P. (Guest)
on 2009-05-12 11:24
(Received via mailing list)
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 C.
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_g...
- "If voting changed anything, they'd make it illegal."
Curt H. (Guest)
on 2009-05-12 18:54
(Received via mailing list)
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: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] 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 C.
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_g...
- "If voting changed anything, they'd make it illegal."
Ivan P. (Guest)
on 2009-05-12 19:48
(Received via mailing list)
Cool that's what I figured was going on.I will have to invert the way
I'm
creating proxies now but that's no problem.


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

Charles
Kuralt<http://www.brainyquote.com/quotes/authors/c/charle...
- "You can find your way across this country using burger joints the
way a
navigator uses stars."
Ivan P. (Guest)
on 2009-05-13 00:24
(Received via mailing list)
About the metadata.. I think in my case it would be great if I could
redirect the methods on the type to methods on a property of that type.
So for the ShurikenProxy class I would like to say that it needs to
forward
all method calls to the property subject for example possibly with an
exception list of methods that won't be forwarded. I guess that would
get me
the behavior I'm expecting. Would that be possible?
---
Met vriendelijke groeten - Best regards - Salutations
Ivan Porto C.
Blog: http://flanders.co.nz
Twitter: http://twitter.com/casualjim
Author of IronRuby in Action (http://manning.com/carrero)
Curt H. (Guest)
on 2009-05-13 00:44
(Received via mailing list)
But this redirection can be done entirely at the level of Ruby
metaprogramming, can’t it. I’m pretty sure I’ve seen Proxy objects
defined in ActiveSupport that do something quite similar. (Full
disclosure, though: I’m really a Ruby noob.)

By contrast, consider the following

class C
  clr_property :Value, System::Int32, ::get_value, ::set_value

  def get_value
    42
  end
  def set_value
    raise RuntimeError, 'Read-only, sucker!'
  end
end

The hypothetical class method clr_property might set some kind of
metadata on the class which would be picked up by the CLS type
generator, and turned into a CLS-visible property on the generated type
with getter and setter methods. This is the sort of thing I had in mind
when I described “additional metadata”.

From: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Ivan Porto
Carrero
Sent: Tuesday, May 12, 2009 12:58 PM
To: removed_email_address@domain.invalid
Subject: Re: [Ironruby-core] interop question

About the metadata.. I think in my case it would be great if I could
redirect the methods on the type to methods on a property of that type.

So for the ShurikenProxy class I would like to say that it needs to
forward all method calls to the property subject for example possibly
with an exception list of methods that won't be forwarded. I guess that
would get me the behavior I'm expecting. Would that be possible?
---
Met vriendelijke groeten - Best regards - Salutations
Ivan Porto C.
Blog: http://flanders.co.nz
Twitter: http://twitter.com/casualjim
Author of IronRuby in Action (http://manning.com/carrero)

On Tue, May 12, 2009 at 4:49 PM, Curt H.
<removed_email_address@domain.invalid<mailto:removed_email_address@domain.invalid>> 
wrote:

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:
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 Ivan Porto C.
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 C.
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_g...
- "If voting changed anything, they'd make it illegal."

_______________________________________________
Ironruby-core mailing list
removed_email_address@domain.invalid<mailto:removed_email_address@domain.invalid>
http://rubyforge.org/mailman/listinfo/ironruby-core
Ivan P. (Guest)
on 2009-05-13 00:57
(Received via mailing list)
That would be great for databinding wpf :)
---
Met vriendelijke groeten - Best regards - Salutations
Ivan Porto C.
Blog: http://flanders.co.nz
Twitter: http://twitter.com/casualjim
Author of IronRuby in Action (http://manning.com/carrero)

Vince
Lombardi<http://www.brainyquote.com/quotes/authors/v/vince_...
- "We didn't lose the game; we just ran out of time."
This topic is locked and can not be replied to.