知乎周源微信_每周源代码16-风管磁带版

知乎周源微信

知乎周源微信

duct-tape-roll

A few weeks ago I interviewed Steven Frank (blog), co-owner of Panic and a Mac Developer (who I went to college with). After that interview I stumbled upon the very recently release NSDuctTape project. First, how can you not like a project named after Duct Tape. Second, whenever I hear that some code will bridge to completely incongruent and unbridgeable things, I gotta check it out. What can I say, if there's a freak somewhere that promises to tape two things together, I want to see it! ;) (And I mean freak in the most positive way!)

几周前,我采访了Panic的共同所有者,Mac开发人员(与我一起上大学)的Steven Frank (博客)。 采访之后,我偶然发现了最近发布的NSDuctTape项目。 首先,您怎么可能不喜欢以Duct Tape命名的项目。 其次,每当我听到一些代码将桥接到完全不一致和不可桥接的内容时,我就必须进行检查。 我要说的是,如果某个地方有一个怪胎,承诺将两件事绑在一起,我想看看! ;)(我的意思是最积极的态度!)

NSDuctTape is niche, to be clear, but if you want to write .NET code using Mono on the Mac and you want access to the Objective C Cocoa libraries, this is your one-stop shop. (NOTE: If you do download his source, you'll likely have to pull the files out one at a time because there's Mac files in the zip with the same names as folders and Windows doesn't like it.)

NSDuctTape很明显,但是如果您想在Mac上使用Mono编写.NET代码,并且想要访问Objective C Cocoa库,这是您的一站式商店。 (注意:如果您确实下载了他的源代码,则可能必须一次将一个文件拉出,因为zip中有Mac文件,其名称与文件夹相同,而Windows不喜欢。)

And so, Dear Reader, I present to you sixteenth in a infinite number of posts of "The Weekly Source Code." Here's some source I was reading this week.

因此,尊敬的读者,我每周源代码的无数帖子中向您展示了第十六位。 这是我本周正在阅读的一些资料。

Dave, the author, hasn't check on Mono's support for Linq, but he uses C# 3.0 features to create his own LINQ-lite helper methods. I found this to be a clever "punt."

作者Dave尚未检查Mono对Linq的支持,但他使用C#3.0功能来创建自己的LINQ-lite辅助方法。 我发现这是一个聪明的“平底锅”。

	
internal static class Enumerable
{
	public static IEnumerable
   
   
    
     Select
    
    
     
     (IEnumerable
     
     
      
       list, Converter
      
      
       
        convert)
	{
		foreach (TInput value in list)
			yield return convert(value);
	}

	public static IEnumerable
       
       
         SelectMany 
        
          (IEnumerable 
         
           list, Converter 
           
           
             > convert) { foreach (TInput value in list) foreach (TOutput converted in convert(value)) yield return converted; } public static IEnumerable 
            
              Where 
             
               (IEnumerable 
              
                list, Predicate 
               
                 predicate) { foreach (T value in list) if (predicate(value)) yield return value; } public static List 
                
                  ToList 
                 
                   (IEnumerable 
                  
                    list) { List 
                   
                     result = list as List 
                    
                      ; return result ?? new List 
                     
                       (list); } public static T[] ToArray 
                      
                        (IEnumerable 
                       
                         list) { return ToList(list).ToArray(); } } 
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

Because he's "thunking" (not the technically accurate word, but I like saying it) down into unmanaged code that needs to have handles allocated and deallocated, he creates an HGlobal wrapper class using my most favorite .NET BCL pattern, IDisposable. Classic stuff, simple and works great.

因为他在“ thunking”(不是技术上准确的词,但我喜欢说),变成需要分配和释放句柄的非托管代码,所以他使用我最喜欢的.NET BCL模式IDisposable创建了HGlobal包装器类。 经典的东西,简单,效果很好。

...snip...

public void Dispose()
{
	if (_hGlobal != IntPtr.Zero)
		Marshal.FreeHGlobal(_hGlobal);
	_hGlobal = IntPtr.Zero;
}

private DisposableHGlobal(IntPtr hGlobal)
{
	_hGlobal = hGlobal;
}

public static DisposableHGlobal StructureToHGlobal
   
   
    
    (T value)
	where T : struct
{
	DisposableHGlobal result = new DisposableHGlobal(Marshal.SizeOf(value));
	Marshal.StructureToPtr(value, result.ToIntPtr(), false);
	return result;
}
...snip...
   
   

Finally, in his application managed "wrapper" he spins through his chosen System.Types and registers each of them with ObjectiveC. This interop is one way, meaning that he's choosing to expose his .NET types as Objective C classes.

最后,在他的应用程序管理的“包装器”中,他浏览了自己选择的System.Types并向ObjectiveC注册了它们。 这种互操作是一种方式,这意味着他选择将.NET类型公开为Objective C类。

public static void Run(string nibFile, IEnumerable
   
   
    
     exposedTypes)
{
	ObjectiveCClass nsAutoReleasePoolClass = ObjectiveCClass.GetClass("NSAutoreleasePool");
	IntPtr autoReleasePool = nsAutoReleasePoolClass.Instantiate();
	ObjectiveCMethods.SendMessage(autoReleasePool, ObjectiveCMethods.SelectorFromString("init"));
	try
	{
		IntPtr process = IntPtr.Zero;
		GetCurrentProcess(ref process);
		TransformProcessType(ref process, ProcessType.ForegroundApplication);
		SetFrontProcess(ref process);

		Registrar.Initialize();

		foreach (Type type in exposedTypes)
		{
			ObjectiveCNameAttribute attribute = MemberInfoUtility.GetCustomAttribute
    
    
     
     (type);
			
     
     Registrar.RegisterClass(attribute != null ? attribute.Name : type.Name, type);
		}

		ObjectiveCClass nsBundleClass = ObjectiveCClass.GetClass("NSBundle");
		IntPtr name = NativeString.StringToNativeString(nibFile);
		ObjectiveCClass nsDictionaryClass = ObjectiveCClass.GetClass("NSDictionary");
		IntPtr key = NativeString.StringToNativeString("NSOwner");
		ObjectiveCClass nsApplicationClass = ObjectiveCClass.GetClass("NSApplication");
		IntPtr sharedApplication = ObjectiveCMethods.SendMessage(nsApplicationClass.ToIntPtr(), ObjectiveCMethods.SelectorFromString("sharedApplication"));
		IntPtr nsDictionary = ObjectiveCMethods.SendMessage(nsDictionaryClass.ToIntPtr(), ObjectiveCMethods.SelectorFromString("dictionaryWithObject:forKey:"), sharedApplication, key);
		IntPtr zone = ObjectiveCMethods.SendMessage(sharedApplication, ObjectiveCMethods.SelectorFromString("zone"));
		ObjectiveCMethods.SendMessage(nsBundleClass.ToIntPtr(), ObjectiveCMethods.SelectorFromString("loadNibFile:externalNameTable:withZone:"), name, nsDictionary, zone);

		ObjectiveCMethods.SendMessage(sharedApplication, ObjectiveCMethods.SelectorFromString("run"));
	}
	finally
	{
		ObjectiveCMethods.SendMessage(autoReleasePool, ObjectiveCMethods.SelectorFromString("release"));
		autoReleasePool = IntPtr.Zero;
	}
}
    
    
   
   

It's inside the RegisterClass where he creates Objective C classes for each .NET class, lazily making class definitions, and poking values into them. He's using "reflection" on both sides...reflecting over the .NET types, methods, etc and dynamically creating the same types, methods, etc on the ObjectiveC side.

在RegisterClass内部,他为每个.NET类创建Objective C类,懒惰地创建类定义,然后将值放入其中。 他在两边都使用“反射” ...反射.NET类型,方法等,并在ObjectiveC方面动态创建相同的类型,方法等。

Freaky and fun!

怪异而有趣!

翻译自: https://www.hanselman.com/blog/the-weekly-source-code-16-duct-tape-edition

知乎周源微信

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值