CLR via C#:与WinRT组件互操作

基础知识:如下所示:
1.WinRT组件使用由ECMA协会标准化的.NET元数据格式(ECMA-335)来描述其API,这些元数据会嵌入到扩展名为.winmd的文件中。
2.RCW(运行时可调用包装器)内部引用了WinRT组件。
3.CCW(COM可调用包装器)内部引用了CLR对象。

CLR投射:CLR通过元数据将WinRT类型隐式投射成FCL类型。

框架投射:CLR通过代码将WinRT类型显式投射成FCL类型。具有以下特性:
1.可以使用WindowsRuntimeSystemExtensions类中的辅助函数来完成.NET异步调用WinRT。
2.可以使用WindowsRuntimeStorageExtensions和WindowsRuntimeStreamExtensions类中的辅助函数来完成.NET和WinRT之间互传输数据流。
3.可以使用WindowsRuntimeBufferExtensions类中的辅助函数来完成.NET和WinRT之间传输数据块。

用C#定义WinRT组件:具有以下特性:
1.使用该WinRT组件时,一般会造成的额外性能损失和内存消耗。
2.使用ildasm的/project命令开关可以查看将WinRT类型投射成FCL等价类型之后的元数据。
3.C#实现WinRT组件的模板如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Metadata;

// The namespace MUST match the assembly name and cannot be "Windows"
namespace LearnCLR.WinRTComponents {
   // [Flags]  // Must not be present if enum is int; required if enum is uint
   public enum WinRTEnum : int {    // Enums must be backed by int or uint
      None,
      NotNone
   }

   // Structures can only contain core data types, String, & other structures
   // No constructors or methods are allowed
   public struct WinRTStruct {
      public Int32 ANumber;
      public String AString;
      public WinRTEnum AEnum;    // Really just a 32-bit integer
   }

   // Delegates must have WinRT-compatible types in the signature (no BeginInvoke/EndInvoke)
   public delegate String WinRTDelegate(Int32 x);

   // Interfaces can have methods, properties, & events but cannot be generic.
   public interface IWinRTInterface {
      // Nullable<T> marshals as IReference<T>
      Int32? InterfaceProperty { get; set; }
   }

   // Members without a [Version(#)] attribute default to the class's 
   // version (1) and are part of the same underlying COM interface
   // produced by WinMDExp.exe.
   [Version(1)]
   // Class must be derived from Object, sealed, not generic, 
   // implement only WinRT interfaces, & public members must be WinRT types
   public sealed class WinRTClass : IWinRTInterface {
      // Public fields are not allowed 

      #region Class can expose static methods, properties, and events
      public static String StaticMethod(String s) { return "Returning " + s; }
      public static WinRTStruct StaticProperty { get; set; }

      // In JavaScript 'out' parameters are returned as objects with each 
      // parameter becoming a property along with the return value
      public static String OutParameters(out WinRTStruct x, out Int32 year) {
         x = new WinRTStruct { AEnum = WinRTEnum.NotNone, ANumber = 333, AString = "Jeff" };
         year = DateTimeOffset.Now.Year;
         return "Grant";
      }
      #endregion

      // Constructor can take arguments but not out/ref arguments
      public WinRTClass(Int32? number) { InterfaceProperty = number; }

      public Int32? InterfaceProperty { get; set; }

      // Only ToString is allowed to be overridden
      public override String ToString() {
         return String.Format("InterfaceProperty={0}",
            InterfaceProperty.HasValue ? InterfaceProperty.Value.ToString() : "(not set)");
      }

      public void ThrowingMethod() {
         throw new InvalidOperationException("My exception message");

         // To throw a specific HRESULT, use COMException instead
         //const Int32 COR_E_INVALIDOPERATION = unchecked((Int32)0x80131509);
         //throw new COMException("Invalid Operation", COR_E_INVALIDOPERATION);
      }

      #region Arrays are passed, returned OR filled; never a combination
      public Int32 PassArray([ReadOnlyArray] /* [In] implied */ Int32[] data) {
         // NOTE: Modified array contents MAY not be marshaled out; do not modify the array
         return data.Sum();
      }

      public Int32 FillArray([WriteOnlyArray] /* [Out] implied */ Int32[] data) {
         // NOTE: Original array contents MAY not be marshaled in; 
         // write to the array before reading from it
         for (Int32 n = 0; n < data.Length; n++) data[n] = n;
         return data.Length;
      }

      public Int32[] ReturnArray() {
         // Array is marshaled out upon return
         return new Int32[] { 1, 2, 3 };
      }
      #endregion

      // Collections are passed by reference
      public void PassAndModifyCollection(IDictionary<String, Object> collection) {
         collection["Key2"] = "Value2";  // Modifies collection in place via interop
      }

      #region Method overloading
      // Overloads with same # of parameters are considered identical to JavaScript
      public void SomeMethod(Int32 x) { }

      [Windows.Foundation.Metadata.DefaultOverload]  // Attribute makes this method the default overload
      public void SomeMethod(String s) { }
      #endregion

      #region Automatically implemented event
      public event WinRTDelegate AutoEvent;

      public String RaiseAutoEvent(Int32 number) {
         WinRTDelegate d = AutoEvent;
         return (d == null) ? "No callbacks registered" : d(number);
      }
      #endregion

      #region Manually implemented event
      // Private field that keeps track of the event's registered delegates
      private EventRegistrationTokenTable<WinRTDelegate> m_manualEvent = null;

      // Manual implementation of the event's add and remove methods
      public event WinRTDelegate ManualEvent {
         add {
            // Gets the existing table, or creates a new one if the table is not yet initialized
            return EventRegistrationTokenTable<WinRTDelegate>
               .GetOrCreateEventRegistrationTokenTable(ref m_manualEvent).AddEventHandler(value);
         }
         remove {
            EventRegistrationTokenTable<WinRTDelegate>
               .GetOrCreateEventRegistrationTokenTable(ref m_manualEvent).RemoveEventHandler(value);
         }
      }

      public String RaiseManualEvent(Int32 number) {
         WinRTDelegate d = EventRegistrationTokenTable<WinRTDelegate>
            .GetOrCreateEventRegistrationTokenTable(ref m_manualEvent).InvocationList;
         return (d == null) ? "No callbacks registered" : d(number);
      }
      #endregion

      #region Asynchronous methods
      // Async methods MUST return IAsync[Action|Operation](WithProgress)
      // NOTE: Other languages see the DataTimeOffset as Windows.Foundation.DateTime
      public IAsyncOperationWithProgress<DateTimeOffset, Int32> DoSomethingAsync() {
         // Use the System.Runtime.InteropServices.WindowsRuntime.AsyncInfo's Run methods to 
         // invoke a private method written entirely in managed code
         return AsyncInfo.Run<DateTimeOffset, Int32>(DoSomethingAsyncInternal);
      }

      // Implement the async operation via a private method using normal .NET technologies
      private async Task<DateTimeOffset> DoSomethingAsyncInternal(
         CancellationToken ct, IProgress<Int32> progress) {

         for (Int32 x = 0; x < 10; x++) {
            // This code supports cancellation and progress reporting
            ct.ThrowIfCancellationRequested();
            if (progress != null) progress.Report(x * 10);
            await Task.Delay(1000); // Simulate doing something asynchronously
         }
         return DateTimeOffset.Now; // Ultimate return value
      }

      public IAsyncOperation<DateTimeOffset> DoSomethingAsync2() {
         // If you don't need cancellation & progress, use 
         // System.WindowsRuntimeSystemExtensions' AsAsync[Action|Operation] Task 
         // extension methods (these call AsyncInfo.Run internally)
         return DoSomethingAsyncInternal(default(CancellationToken), null).AsAsyncOperation();
      }
      #endregion

      // After you ship a version, mark new members with a [Version(#)] attribute
      // so that WinMDExp.exe puts the new members in a different underlying COM 
      // interface. This is required since COM interfaces are supposed to be immutable.
      [Version(2)]
      public void NewMethodAddedInV2() { }
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值