当前位置: 首页 > 工具软件 > IronRuby > 使用案例 >

Ironruby和C#互相调用例子收集

闻人嘉木
2023-12-01
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Microsoft.Scripting.Hosting;
using IronRuby.Runtime;
using IronRuby;
using Microsoft.Scripting.Hosting.Providers;
using Microsoft.Scripting;
using IronRuby.Builtins;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Scripting.Math;

namespace Test
{
	[TestClass]
	public class UnitTest1
	{
		#region 初始化

		public ScriptRuntime Runtime { get; private set; }
		public RubyContext Context { get; private set; }
		public ScriptEngine Engine { get; private set; }
		[TestInitialize]
		public void Init()
		{
			var setup = ScriptRuntimeSetup.ReadConfiguration();
			setup.AddRubySetup();
			setup.PrivateBinding = true;
			Runtime = Ruby.CreateRuntime(setup);
			Engine = Ruby.GetEngine(Runtime);

			Context = (RubyContext)HostingHelpers.GetLanguageContext(Engine);
			Engine.Execute("1");//完全初始化
		}
		#endregion

		//ruby对象转C#对象
		[TestMethod]
		public void SetGlobalVariable1()
		{

			dynamic obj;
			//字符串
			obj = Engine.Execute("'123'");
			Assert.AreEqual(typeof(MutableString), obj.GetType());
			Assert.AreEqual("123", obj.ToString());

			//浮点数
			obj = Engine.Execute("2.102");
			Assert.AreEqual(typeof(double), obj.GetType());
			Assert.AreEqual(2.102, obj);

			//整数
			obj = Engine.Execute("123");
			Assert.AreEqual(typeof(int), obj.GetType());
			Assert.AreEqual(123, obj);

			//大整数(超过Int32则返回大整数)
			obj = Engine.Execute("123456789123456789");
			Assert.AreEqual(typeof(BigInteger), obj.GetType());
			Assert.AreEqual(123456789123456789, obj);

			//数组
			obj = Engine.Execute("[1,2,3]");
			Assert.AreEqual(typeof(RubyArray), obj.GetType());
			Assert.IsTrue(new int[] { 1, 2, 3 }.SequenceEqual((obj as RubyArray).OfType<int>().ToArray()));

		}

		//C#向ruby传递全局变量
		[TestMethod]
		public void SetGlobalVariable()
		{
			Context.SetGlobalVariable(null, "var1", "123");
			Assert.AreEqual("123abc", Engine.Execute("$var1+'abc'").ToString());
		}

		//ruby引用C#程序集, 命名空间和类, 调用C#扩展函数
		[TestMethod]
		public void Include()
		{
			Context.SetGlobalVariable(null, "list", new List<int> { 1, 2, 3 });
			var re = Engine.Execute(@"
				load_assembly 'Microsoft.VisualStudio.TestPlatform.TestFramework'		#加载程序集
				include Microsoft::VisualStudio::TestTools::UnitTesting
				load_assembly 'System.Core'		#加载程序集
				include System::Text			#命名空间
				using_clr_extensions System::Linq	#引用扩展函数
				
				sb1 = StringBuilder.new
				sb2 = System::Text::StringBuilder.new #不使用include直接引用类
				Assert.IsTrue(sb1.GetType == sb2.GetType)
				Assert.AreEqual(3, $list.Max)		#调用扩展函数Enumerable.Sum
");

		}


		static string GetGenericType1<T>()
		{
			return typeof(T).Name;
		}
		static string GetGenericType2<T1, T2, T3>()
		{
			return typeof(T1).Name + "," + typeof(T2).Name + "," + typeof(T3).Name;
		}
		//泛型相关
		[TestMethod]
		public void Generic()
		{
			Engine.Execute(@"
				load_assembly 'Microsoft.VisualStudio.TestPlatform.TestFramework'		#加载程序集
				include Microsoft::VisualStudio::TestTools::UnitTesting
				include System
				#使用方括号或of方法传递泛型参数
				int_list_type = System::Collections::Generic::List[Int32]  #获取泛型类型(MakeGenericType)
				list = int_list_type.new
				list.Add 1
				list.Add 2
				list.Add 3
				Assert.AreEqual 3,list.Count

				#2种方法一样效果
				Assert.AreEqual Tuple.of(Int32,Single,Double).new(1,2.1,3.2) , Tuple[Int32,Single,Double].new(1,2.1,3.2)

				load_assembly 'Test'
				Assert.AreEqual 'Int32,Single,Double',Test::UnitTest1.method(:GetGenericType2).of(Int32,Single,Double)[].to_s #调用泛型函数, 只能使用of
");
		}

		//block必须放在第一个参数
		static object ReceiveBlock(BlockParam block, string arg1, string arg2)
		{
			//调用block
			return ((dynamic)block.Proc).call(arg1, arg2);
		}
		static object BlockBindSelf(BlockParam block, object self)
		{
			//使用指定的self调用block
			return RubyOps.Yield0(block.Proc, self, block);
		}

		//ruby block相关
		[TestMethod]
		public void Block()
		{
			Engine.Execute(@"
				load_assembly 'Microsoft.VisualStudio.TestPlatform.TestFramework'		#加载程序集
				include Microsoft::VisualStudio::TestTools::UnitTesting
				include System
				load_assembly 'Test'

				Assert.AreEqual '123abc',Test::UnitTest1.ReceiveBlock('123','abc'){|a,b| a + b }
				Assert.AreEqual '123',Test::UnitTest1.BlockBindSelf('123'){ self }
");
		}
		class EventTest
		{
			public event EventHandler<string> OnEvent;
			public void Send(string msg)
			{
				OnEvent?.Invoke(this, msg);
			}
		}
		//C#事件相关
		[TestMethod]
		public void Event()
		{
			Engine.Execute(@"
				load_assembly 'Microsoft.VisualStudio.TestPlatform.TestFramework'		#加载程序集
				include Microsoft::VisualStudio::TestTools::UnitTesting
				load_assembly 'Test'

				ev = Test::UnitTest1::EventTest.new #内部类使用双冒号来引用
				ev.OnEvent {
					|sender, msg|
					$msg = msg
				}
				ev.Send '123'
				Assert.AreEqual '123',$msg
");
		}
		//ruby实现c#接口
		[TestMethod]
		public void Interface()
		{
			ICloneable obj = Engine.Execute(@"
				class A
					include System::ICloneable
					def Clone
						self
					end
				end
				A.new
");
			Assert.AreEqual(obj, obj.Clone());
		}

		public interface ISpeaker
		{
			string Speak();
		}
		public class Speaker : ISpeaker
		{
			public string Speak()
			{
				return "hello";
			}
		}

		//open class/interface
		[TestMethod]
		public void MyTestMethod()
		{
			Context.SetGlobalVariable(null, "speaker", new Speaker());
			Engine.Execute(@"
				load_assembly 'Microsoft.VisualStudio.TestPlatform.TestFramework'		#加载程序集
				include Microsoft::VisualStudio::TestTools::UnitTesting
				load_assembly 'Test'

				module Test::UnitTest1::ISpeaker #为接口添加扩展方法(仅支持在ruby中调用)
					def interface_speak
						self.Speak+', ISpeaker'
					end
				end

				class Test::UnitTest1::Speaker #为类添加扩展方法(仅支持在ruby中调用)
					def class_speak
						self.Speak+', Speaker'
					end
				end

				Assert.AreEqual 'hello, Speaker', $speaker.class_speak
				Assert.AreEqual 'hello, ISpeaker', $speaker.interface_speak
");
		}

	}


}

 类似资料: