Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System / compmod / system / collections / specialized / marshalinghelpers.cs
blobed712071802a3c7639edd1a23cd03efb7afeccea
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 //
7 // <OWNER>Microsoft</OWNER>
9 using System.Security;
10 using System.Collections;
11 using System.ComponentModel;
12 using System.Diagnostics.Contracts;
13 using System.Collections.Specialized;
14 using System.Runtime.CompilerServices;
15 using System.Windows.Input;
17 namespace System.Runtime.InteropServices.WindowsRuntime
19 // Local definition of Windows.UI.Xaml.Interop.INotifyCollectionChangedEventArgs
20 [ComImport]
21 [Guid("4cf68d33-e3f2-4964-b85e-945b4f7e2f21")]
22 [WindowsRuntimeImport]
23 internal interface INotifyCollectionChangedEventArgs
25 NotifyCollectionChangedAction Action { get; }
26 IList NewItems { get; }
27 IList OldItems { get; }
28 int NewStartingIndex { get; }
29 int OldStartingIndex { get; }
32 // Local definition of Windows.UI.Xaml.Data.IPropertyChangedEventArgs
33 [ComImport]
34 [Guid("4f33a9a0-5cf4-47a4-b16f-d7faaf17457e")]
35 [WindowsRuntimeImport]
36 internal interface IPropertyChangedEventArgs
38 string PropertyName { get; }
41 // Local definition of Windows.UI.Xaml.Interop.INotifyCollectionChanged
42 [ComImport]
43 [Guid("28b167d5-1a31-465b-9b25-d5c3ae686c40")]
44 [WindowsRuntimeImport]
45 internal interface INotifyCollectionChanged_WinRT
47 EventRegistrationToken add_CollectionChanged(NotifyCollectionChangedEventHandler value);
48 void remove_CollectionChanged(EventRegistrationToken token);
51 // Local definition of Windows.UI.Xaml.Data.INotifyPropertyChanged
52 [ComImport]
53 [Guid("cf75d69c-f2f4-486b-b302-bb4c09baebfa")]
54 [WindowsRuntimeImport]
55 internal interface INotifyPropertyChanged_WinRT
57 EventRegistrationToken add_PropertyChanged(PropertyChangedEventHandler value);
58 void remove_PropertyChanged(EventRegistrationToken token);
61 // Local definition of Windows.UI.Xaml.Input.ICommand
62 [ComImport]
63 [Guid("e5af3542-ca67-4081-995b-709dd13792df")]
64 [WindowsRuntimeImport]
65 internal interface ICommand_WinRT
67 EventRegistrationToken add_CanExecuteChanged(EventHandler<object> value);
68 void remove_CanExecuteChanged(EventRegistrationToken token);
69 bool CanExecute(object parameter);
70 void Execute(object parameter);
73 // Local definition of Windows.UI.Xaml.Interop.NotifyCollectionChangedEventHandler
74 [Guid("ca10b37c-f382-4591-8557-5e24965279b0")]
75 [WindowsRuntimeImport]
76 internal delegate void NotifyCollectionChangedEventHandler_WinRT(object sender, NotifyCollectionChangedEventArgs e);
78 // Local definition of Windows.UI.Xaml.Data.PropertyChangedEventHandler
79 [Guid("50f19c16-0a22-4d8e-a089-1ea9951657d2")]
80 [WindowsRuntimeImport]
81 internal delegate void PropertyChangedEventHandler_WinRT(object sender, PropertyChangedEventArgs e);
83 internal static class NotifyCollectionChangedEventArgsMarshaler
85 // Extracts properties from a managed NotifyCollectionChangedEventArgs and passes them to
86 // a VM-implemented helper that creates a WinRT NotifyCollectionChangedEventArgs instance.
87 // This method is called from IL stubs and needs to have its token stabilized.
88 [SecurityCritical]
89 static internal IntPtr ConvertToNative(NotifyCollectionChangedEventArgs managedArgs)
91 if (managedArgs == null)
92 return IntPtr.Zero;
94 return System.StubHelpers.EventArgsMarshaler.CreateNativeNCCEventArgsInstance(
95 (int)managedArgs.Action,
96 managedArgs.NewItems,
97 managedArgs.OldItems,
98 managedArgs.NewStartingIndex,
99 managedArgs.OldStartingIndex);
102 // Extracts properties from a WinRT NotifyCollectionChangedEventArgs and creates a new
103 // managed NotifyCollectionChangedEventArgs instance.
104 // This method is called from IL stubs and needs to have its token stabilized.
105 [SecurityCritical]
106 static internal NotifyCollectionChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
108 if (nativeArgsIP == IntPtr.Zero)
109 return null;
111 object obj = System.StubHelpers.InterfaceMarshaler.ConvertToManagedWithoutUnboxing(nativeArgsIP);
112 INotifyCollectionChangedEventArgs nativeArgs = (INotifyCollectionChangedEventArgs)obj;
114 return new NotifyCollectionChangedEventArgs(
115 nativeArgs.Action,
116 nativeArgs.NewItems,
117 nativeArgs.OldItems,
118 nativeArgs.NewStartingIndex,
119 nativeArgs.OldStartingIndex);
123 internal static class PropertyChangedEventArgsMarshaler
125 // Extracts PropertyName from a managed PropertyChangedEventArgs and passes them to
126 // a VM-implemented helper that creates a WinRT PropertyChangedEventArgs instance.
127 // This method is called from IL stubs and needs to have its token stabilized.
128 [SecurityCritical]
129 static internal IntPtr ConvertToNative(PropertyChangedEventArgs managedArgs)
131 if (managedArgs == null)
132 return IntPtr.Zero;
134 return System.StubHelpers.EventArgsMarshaler.CreateNativePCEventArgsInstance(managedArgs.PropertyName);
137 // Extracts properties from a WinRT PropertyChangedEventArgs and creates a new
138 // managed PropertyChangedEventArgs instance.
139 // This method is called from IL stubs and needs to have its token stabilized.
140 [SecurityCritical]
141 static internal PropertyChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
143 if (nativeArgsIP == IntPtr.Zero)
144 return null;
146 object obj = System.StubHelpers.InterfaceMarshaler.ConvertToManagedWithoutUnboxing(nativeArgsIP);
147 IPropertyChangedEventArgs nativeArgs = (IPropertyChangedEventArgs)obj;
149 return new PropertyChangedEventArgs(nativeArgs.PropertyName);
153 // This is a set of stub methods implementing the support for the managed INotifyCollectionChanged
154 // interface on WinRT objects that support the WinRT INotifyCollectionChanged. Used by the interop
155 // mashaling infrastructure.
156 internal sealed class NotifyCollectionChangedToManagedAdapter
158 private NotifyCollectionChangedToManagedAdapter()
160 Contract.Assert(false, "This class is never instantiated");
163 internal event NotifyCollectionChangedEventHandler CollectionChanged
165 // void CollectionChanged.add(NotifyCollectionChangedEventHandler)
166 [SecurityCritical]
169 INotifyCollectionChanged_WinRT _this = JitHelpers.UnsafeCast<INotifyCollectionChanged_WinRT>(this);
171 // call the WinRT eventing support in mscorlib to subscribe the event
172 Func<NotifyCollectionChangedEventHandler, EventRegistrationToken> addMethod =
173 new Func<NotifyCollectionChangedEventHandler, EventRegistrationToken>(_this.add_CollectionChanged);
174 Action<EventRegistrationToken> removeMethod =
175 new Action<EventRegistrationToken>(_this.remove_CollectionChanged);
177 WindowsRuntimeMarshal.AddEventHandler<NotifyCollectionChangedEventHandler>(addMethod, removeMethod, value);
180 // void CollectionChanged.remove(NotifyCollectionChangedEventHandler)
181 [SecurityCritical]
182 remove
184 INotifyCollectionChanged_WinRT _this = JitHelpers.UnsafeCast<INotifyCollectionChanged_WinRT>(this);
186 // call the WinRT eventing support in mscorlib to unsubscribe the event
187 Action<EventRegistrationToken> removeMethod =
188 new Action<EventRegistrationToken>(_this.remove_CollectionChanged);
190 WindowsRuntimeMarshal.RemoveEventHandler<NotifyCollectionChangedEventHandler>(removeMethod, value);
195 // This is a set of stub methods implementing the support for the WinRT INotifyCollectionChanged
196 // interface on managed objects that support the managed INotifyCollectionChanged. Used by the interop
197 // mashaling infrastructure.
198 internal sealed class NotifyCollectionChangedToWinRTAdapter
200 private NotifyCollectionChangedToWinRTAdapter()
202 Contract.Assert(false, "This class is never instantiated");
205 // An instance field typed as EventRegistrationTokenTable is injected into managed classed by the compiler when compiling for /t:winmdobj.
206 // Since here the class can be an arbitrary implementation of INotifyCollectionChanged, we have to keep the EventRegistrationTokenTable's
207 // separately, associated with the implementations using ConditionalWeakTable.
208 private static ConditionalWeakTable<INotifyCollectionChanged, EventRegistrationTokenTable<NotifyCollectionChangedEventHandler>> m_weakTable =
209 new ConditionalWeakTable<INotifyCollectionChanged, EventRegistrationTokenTable<NotifyCollectionChangedEventHandler>>();
211 // EventRegistrationToken CollectionChanged.add(NotifyCollectionChangedEventHandler value)
212 [SecurityCritical]
213 internal EventRegistrationToken add_CollectionChanged(NotifyCollectionChangedEventHandler value)
215 INotifyCollectionChanged _this = JitHelpers.UnsafeCast<INotifyCollectionChanged>(this);
216 EventRegistrationTokenTable<NotifyCollectionChangedEventHandler> table = m_weakTable.GetOrCreateValue(_this);
218 EventRegistrationToken token = table.AddEventHandler(value);
219 _this.CollectionChanged += value;
221 return token;
224 // void CollectionChanged.remove(EventRegistrationToken token)
225 [SecurityCritical]
226 internal void remove_CollectionChanged(EventRegistrationToken token)
228 INotifyCollectionChanged _this = JitHelpers.UnsafeCast<INotifyCollectionChanged>(this);
229 EventRegistrationTokenTable<NotifyCollectionChangedEventHandler> table = m_weakTable.GetOrCreateValue(_this);
231 NotifyCollectionChangedEventHandler handler = table.ExtractHandler(token);
232 if (handler != null)
234 _this.CollectionChanged -= handler;
239 // This is a set of stub methods implementing the support for the managed INotifyPropertyChanged
240 // interface on WinRT objects that support the WinRT INotifyPropertyChanged. Used by the interop
241 // mashaling infrastructure.
242 internal sealed class NotifyPropertyChangedToManagedAdapter
244 private NotifyPropertyChangedToManagedAdapter()
246 Contract.Assert(false, "This class is never instantiated");
249 internal event PropertyChangedEventHandler PropertyChanged
251 // void PropertyChanged.add(PropertyChangedEventHandler)
252 [SecurityCritical]
255 INotifyPropertyChanged_WinRT _this = JitHelpers.UnsafeCast<INotifyPropertyChanged_WinRT>(this);
257 // call the WinRT eventing support in mscorlib to subscribe the event
258 Func<PropertyChangedEventHandler, EventRegistrationToken> addMethod =
259 new Func<PropertyChangedEventHandler, EventRegistrationToken>(_this.add_PropertyChanged);
260 Action<EventRegistrationToken> removeMethod =
261 new Action<EventRegistrationToken>(_this.remove_PropertyChanged);
263 WindowsRuntimeMarshal.AddEventHandler<PropertyChangedEventHandler>(addMethod, removeMethod, value);
266 // void PropertyChanged.remove(PropertyChangedEventHandler)
267 [SecurityCritical]
268 remove
270 INotifyPropertyChanged_WinRT _this = JitHelpers.UnsafeCast<INotifyPropertyChanged_WinRT>(this);
272 // call the WinRT eventing support in mscorlib to unsubscribe the event
273 Action<EventRegistrationToken> removeMethod =
274 new Action<EventRegistrationToken>(_this.remove_PropertyChanged);
276 WindowsRuntimeMarshal.RemoveEventHandler<PropertyChangedEventHandler>(removeMethod, value);
281 // This is a set of stub methods implementing the support for the WinRT INotifyPropertyChanged
282 // interface on managed objects that support the managed INotifyPropertyChanged. Used by the interop
283 // mashaling infrastructure.
284 internal sealed class NotifyPropertyChangedToWinRTAdapter
286 private NotifyPropertyChangedToWinRTAdapter()
288 Contract.Assert(false, "This class is never instantiated");
291 // An instance field typed as EventRegistrationTokenTable is injected into managed classed by the compiler when compiling for /t:winmdobj.
292 // Since here the class can be an arbitrary implementation of INotifyCollectionChanged, we have to keep the EventRegistrationTokenTable's
293 // separately, associated with the implementations using ConditionalWeakTable.
294 private static ConditionalWeakTable<INotifyPropertyChanged, EventRegistrationTokenTable<PropertyChangedEventHandler>> m_weakTable =
295 new ConditionalWeakTable<INotifyPropertyChanged, EventRegistrationTokenTable<PropertyChangedEventHandler>>();
297 // EventRegistrationToken PropertyChanged.add(PropertyChangedEventHandler value)
298 [SecurityCritical]
299 internal EventRegistrationToken add_PropertyChanged(PropertyChangedEventHandler value)
301 INotifyPropertyChanged _this = JitHelpers.UnsafeCast<INotifyPropertyChanged>(this);
302 EventRegistrationTokenTable<PropertyChangedEventHandler> table = m_weakTable.GetOrCreateValue(_this);
304 EventRegistrationToken token = table.AddEventHandler(value);
305 _this.PropertyChanged += value;
307 return token;
310 // void PropertyChanged.remove(EventRegistrationToken token)
311 [SecurityCritical]
312 internal void remove_PropertyChanged(EventRegistrationToken token)
314 INotifyPropertyChanged _this = JitHelpers.UnsafeCast<INotifyPropertyChanged>(this);
315 EventRegistrationTokenTable<PropertyChangedEventHandler> table = m_weakTable.GetOrCreateValue(_this);
317 PropertyChangedEventHandler handler = table.ExtractHandler(token);
318 if (handler != null)
320 _this.PropertyChanged -= handler;
325 // This is a set of stub methods implementing the support for the managed ICommand
326 // interface on WinRT objects that support the WinRT ICommand_WinRT.
327 // Used by the interop mashaling infrastructure.
328 // Instances of this are really RCWs of ICommand_WinRT (not ICommandToManagedAdapter or any ICommand).
329 [SecurityCritical]
330 internal sealed class ICommandToManagedAdapter /*: System.Windows.Input.ICommand*/
332 private static ConditionalWeakTable<EventHandler, EventHandler<object>> m_weakTable =
333 new ConditionalWeakTable<EventHandler, EventHandler<object>>();
335 private ICommandToManagedAdapter()
337 Contract.Assert(false, "This class is never instantiated");
340 private event EventHandler CanExecuteChanged
342 // void CanExecuteChanged.add(EventHandler)
345 ICommand_WinRT _this = JitHelpers.UnsafeCast<ICommand_WinRT>(this);
347 // call the WinRT eventing support in mscorlib to subscribe the event
348 Func<EventHandler<object>, EventRegistrationToken> addMethod =
349 new Func<EventHandler<object>, EventRegistrationToken>(_this.add_CanExecuteChanged);
350 Action<EventRegistrationToken> removeMethod =
351 new Action<EventRegistrationToken>(_this.remove_CanExecuteChanged);
353 // value is of type System.EventHandler, but ICommand_WinRT (and thus WindowsRuntimeMarshal.AddEventHandler)
354 // expects an instance of EventHandler<object>. So we get/create a wrapper of value here.
355 EventHandler<object> handler_WinRT = m_weakTable.GetValue(value, ICommandAdapterHelpers.CreateWrapperHandler);
356 WindowsRuntimeMarshal.AddEventHandler<EventHandler<object>>(addMethod, removeMethod, handler_WinRT);
359 // void CanExecuteChanged.remove(EventHandler)
360 remove
362 ICommand_WinRT _this = JitHelpers.UnsafeCast<ICommand_WinRT>(this);
364 // call the WinRT eventing support in mscorlib to unsubscribe the event
365 Action<EventRegistrationToken> removeMethod =
366 new Action<EventRegistrationToken>(_this.remove_CanExecuteChanged);
368 // value is of type System.EventHandler, but ICommand_WinRT (and thus WindowsRuntimeMarshal.RemoveEventHandler)
369 // expects an instance of EventHandler<object>. So we get/create a wrapper of value here.
371 // Also we do a value check rather than an instance check to ensure that different instances of the same delegates are treated equal.
372 EventHandler<object> handler_WinRT = ICommandAdapterHelpers.GetValueFromEquivalentKey(m_weakTable , value, ICommandAdapterHelpers.CreateWrapperHandler);
373 WindowsRuntimeMarshal.RemoveEventHandler<EventHandler<object>>(removeMethod, handler_WinRT);
377 private bool CanExecute(object parameter)
379 ICommand_WinRT _this = JitHelpers.UnsafeCast<ICommand_WinRT>(this);
380 return _this.CanExecute(parameter);
383 private void Execute(object parameter)
385 ICommand_WinRT _this = JitHelpers.UnsafeCast<ICommand_WinRT>(this);
386 _this.Execute(parameter);
390 // This is a set of stub methods implementing the support for the WinRT ICommand_WinRT
391 // interface on managed objects that support the managed ICommand interface.
392 // Used by the interop mashaling infrastructure.
393 // Instances of this are really CCWs of ICommand (not ICommandToWinRTAdapter or any ICommand_WinRT).
394 [SecurityCritical]
395 internal sealed class ICommandToWinRTAdapter /*: ICommand_WinRT*/
397 private ICommandToWinRTAdapter()
399 Contract.Assert(false, "This class is never instantiated");
402 // An instance field typed as EventRegistrationTokenTable is injected into managed classed by the compiler when compiling for /t:winmdobj.
403 // Since here the class can be an arbitrary implementation of ICommand, we have to keep the EventRegistrationTokenTable's
404 // separately, associated with the implementations using ConditionalWeakTable.
405 private static ConditionalWeakTable<ICommand, EventRegistrationTokenTable<EventHandler>> m_weakTable =
406 new ConditionalWeakTable<ICommand, EventRegistrationTokenTable<EventHandler>>();
408 // EventRegistrationToken PropertyChanged.add(EventHandler<object> value)
409 private EventRegistrationToken add_CanExecuteChanged(EventHandler<object> value)
411 ICommand _this = JitHelpers.UnsafeCast<ICommand>(this);
412 EventRegistrationTokenTable<EventHandler> table = m_weakTable.GetOrCreateValue(_this);
414 EventHandler handler = ICommandAdapterHelpers.CreateWrapperHandler(value);
415 EventRegistrationToken token = table.AddEventHandler(handler);
416 _this.CanExecuteChanged += handler;
418 return token;
421 // void PropertyChanged.remove(EventRegistrationToken token)
422 private void remove_CanExecuteChanged(EventRegistrationToken token)
424 ICommand _this = JitHelpers.UnsafeCast<ICommand>(this);
425 EventRegistrationTokenTable<EventHandler> table = m_weakTable.GetOrCreateValue(_this);
427 EventHandler handler = table.ExtractHandler(token);
428 if (handler != null)
430 _this.CanExecuteChanged -= handler;
434 private bool CanExecute(object parameter)
436 ICommand _this = JitHelpers.UnsafeCast<ICommand>(this);
437 return _this.CanExecute(parameter);
440 private void Execute(object parameter)
442 ICommand _this = JitHelpers.UnsafeCast<ICommand>(this);
443 _this.Execute(parameter);
448 // A couple of ICommand adapter helpers need to be transparent, and so are in their own type
449 internal static class ICommandAdapterHelpers
451 internal static EventHandler<object> CreateWrapperHandler(EventHandler handler)
453 // Check whether it is a round-tripping case i.e. the sender is of the type eventArgs,
454 // If so we use it else we pass EventArgs.Empty
455 return (object sender, object e) =>
457 EventArgs eventArgs = e as EventArgs;
458 handler(sender, (eventArgs == null ? System.EventArgs.Empty : eventArgs));
462 internal static EventHandler CreateWrapperHandler(EventHandler<object> handler)
464 return (object sender, EventArgs e) => handler(sender, e);
467 internal static EventHandler<object> GetValueFromEquivalentKey(
468 ConditionalWeakTable<EventHandler, EventHandler<object>> table,
469 EventHandler key,
470 ConditionalWeakTable<EventHandler, EventHandler<object>>.CreateValueCallback callback)
472 EventHandler<object> value;
474 // Find the key in the table using a value check rather than an instance check.
475 EventHandler existingKey = table.FindEquivalentKeyUnsafe(key, out value);
476 if (existingKey == null)
478 value = callback(key);
479 table.Add(key, value);
482 return value;