Delete FriendAccessAllowedAttribute and associated dead code (#15101)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Runtime / InteropServices / WindowsRuntime / CLRIReferenceImpl.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 //
6
7 using System;
8 using System.Collections;
9 using System.Diagnostics;
10 using System.Reflection;
11 using System.Security;
12
13 namespace System.Runtime.InteropServices.WindowsRuntime
14 {
15     internal sealed class CLRIReferenceImpl<T> : CLRIPropertyValueImpl, IReference<T>, IGetProxyTarget
16     {
17         private T _value;
18
19         public CLRIReferenceImpl(PropertyType type, T obj)
20             : base(type, obj)
21         {
22             Debug.Assert(obj != null, "Must not be null");
23             _value = obj;
24         }
25
26         public T Value
27         {
28             get { return _value; }
29         }
30
31         public override string ToString()
32         {
33             if (_value != null)
34             {
35                 return _value.ToString();
36             }
37             else
38             {
39                 return base.ToString();
40             }
41         }
42
43         object IGetProxyTarget.GetTarget()
44         {
45             return (object)_value;
46         }
47
48         // We have T in an IReference<T>.  Need to QI for IReference<T> with the appropriate GUID, call
49         // the get_Value property, allocate an appropriately-sized managed object, marshal the native object
50         // to the managed object, and free the native method.  Also we want the return value boxed (aka normal value type boxing).
51         //
52         // This method is called by VM.
53         internal static Object UnboxHelper(Object wrapper)
54         {
55             Debug.Assert(wrapper != null);
56             IReference<T> reference = (IReference<T>)wrapper;
57             Debug.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<" + typeof(T) + ">, but that failed.");
58             return reference.Value;
59         }
60     }
61
62     // T can be any WinRT-compatible type
63     internal sealed class CLRIReferenceArrayImpl<T> : CLRIPropertyValueImpl,
64                                                       IGetProxyTarget,
65                                                       IReferenceArray<T>,
66                                                       IList                     // Jupiter data binding needs IList/IEnumerable
67     {
68         private T[] _value;
69         private IList _list;
70
71         public CLRIReferenceArrayImpl(PropertyType type, T[] obj)
72             : base(type, obj)
73         {
74             Debug.Assert(obj != null, "Must not be null");
75
76             _value = obj;
77
78             _list = (IList)_value;
79         }
80
81         public T[] Value
82         {
83             get { return _value; }
84         }
85
86         public override string ToString()
87         {
88             if (_value != null)
89             {
90                 return _value.ToString();
91             }
92             else
93             {
94                 return base.ToString();
95             }
96         }
97
98         //
99         // IEnumerable methods. Used by data-binding in Jupiter when you try to data bind
100         // against a managed array
101         //
102         IEnumerator IEnumerable.GetEnumerator()
103         {
104             return ((IEnumerable)_value).GetEnumerator();
105         }
106
107         //
108         // IList & ICollection methods. 
109         // This enables two-way data binding and index access in Jupiter
110         //
111         Object IList.this[int index]
112         {
113             get
114             {
115                 return _list[index];
116             }
117
118             set
119             {
120                 _list[index] = value;
121             }
122         }
123
124         int IList.Add(Object value)
125         {
126             return _list.Add(value);
127         }
128
129         bool IList.Contains(Object value)
130         {
131             return _list.Contains(value);
132         }
133
134         void IList.Clear()
135         {
136             _list.Clear();
137         }
138
139         bool IList.IsReadOnly
140         {
141             get
142             {
143                 return _list.IsReadOnly;
144             }
145         }
146
147         bool IList.IsFixedSize
148         {
149             get
150             {
151                 return _list.IsFixedSize;
152             }
153         }
154
155         int IList.IndexOf(Object value)
156         {
157             return _list.IndexOf(value);
158         }
159
160         void IList.Insert(int index, Object value)
161         {
162             _list.Insert(index, value);
163         }
164
165         void IList.Remove(Object value)
166         {
167             _list.Remove(value);
168         }
169
170         void IList.RemoveAt(int index)
171         {
172             _list.RemoveAt(index);
173         }
174
175         void ICollection.CopyTo(Array array, int index)
176         {
177             _list.CopyTo(array, index);
178         }
179
180         int ICollection.Count
181         {
182             get
183             {
184                 return _list.Count;
185             }
186         }
187
188         Object ICollection.SyncRoot
189         {
190             get
191             {
192                 return _list.SyncRoot;
193             }
194         }
195
196         bool ICollection.IsSynchronized
197         {
198             get
199             {
200                 return _list.IsSynchronized;
201             }
202         }
203
204         object IGetProxyTarget.GetTarget()
205         {
206             return (object)_value;
207         }
208
209         // We have T in an IReferenceArray<T>.  Need to QI for IReferenceArray<T> with the appropriate GUID, call
210         // the get_Value property, allocate an appropriately-sized managed object, marshal the native object
211         // to the managed object, and free the native method.
212         //
213         // This method is called by VM.
214         internal static Object UnboxHelper(Object wrapper)
215         {
216             Debug.Assert(wrapper != null);
217             IReferenceArray<T> reference = (IReferenceArray<T>)wrapper;
218             Debug.Assert(reference != null, "CLRIReferenceArrayImpl::UnboxHelper - QI'ed for IReferenceArray<" + typeof(T) + ">, but that failed.");
219             T[] marshaled = reference.Value;
220             return marshaled;
221         }
222     }
223
224     // For creating instances of Windows Runtime's IReference<T> and IReferenceArray<T>.
225     internal static class IReferenceFactory
226     {
227         internal static readonly Type s_pointType = Type.GetType("Windows.Foundation.Point, " + AssemblyRef.SystemRuntimeWindowsRuntime);
228         internal static readonly Type s_rectType = Type.GetType("Windows.Foundation.Rect, " + AssemblyRef.SystemRuntimeWindowsRuntime);
229         internal static readonly Type s_sizeType = Type.GetType("Windows.Foundation.Size, " + AssemblyRef.SystemRuntimeWindowsRuntime);
230
231         internal static Object CreateIReference(Object obj)
232         {
233             Debug.Assert(obj != null, "Null should not be boxed.");
234
235             Type type = obj.GetType();
236
237             if (type.IsArray)
238                 return CreateIReferenceArray((Array)obj);
239
240             if (type == typeof(int))
241                 return new CLRIReferenceImpl<int>(PropertyType.Int32, (int)obj);
242             if (type == typeof(String))
243                 return new CLRIReferenceImpl<String>(PropertyType.String, (String)obj);
244             if (type == typeof(byte))
245                 return new CLRIReferenceImpl<byte>(PropertyType.UInt8, (byte)obj);
246             if (type == typeof(short))
247                 return new CLRIReferenceImpl<short>(PropertyType.Int16, (short)obj);
248             if (type == typeof(ushort))
249                 return new CLRIReferenceImpl<ushort>(PropertyType.UInt16, (ushort)obj);
250             if (type == typeof(uint))
251                 return new CLRIReferenceImpl<uint>(PropertyType.UInt32, (uint)obj);
252             if (type == typeof(long))
253                 return new CLRIReferenceImpl<long>(PropertyType.Int64, (long)obj);
254             if (type == typeof(ulong))
255                 return new CLRIReferenceImpl<ulong>(PropertyType.UInt64, (ulong)obj);
256             if (type == typeof(float))
257                 return new CLRIReferenceImpl<float>(PropertyType.Single, (float)obj);
258             if (type == typeof(double))
259                 return new CLRIReferenceImpl<double>(PropertyType.Double, (double)obj);
260             if (type == typeof(char))
261                 return new CLRIReferenceImpl<char>(PropertyType.Char16, (char)obj);
262             if (type == typeof(bool))
263                 return new CLRIReferenceImpl<bool>(PropertyType.Boolean, (bool)obj);
264             if (type == typeof(Guid))
265                 return new CLRIReferenceImpl<Guid>(PropertyType.Guid, (Guid)obj);
266             if (type == typeof(DateTimeOffset))
267                 return new CLRIReferenceImpl<DateTimeOffset>(PropertyType.DateTime, (DateTimeOffset)obj);
268             if (type == typeof(TimeSpan))
269                 return new CLRIReferenceImpl<TimeSpan>(PropertyType.TimeSpan, (TimeSpan)obj);
270             if (type == typeof(Object))
271                 return new CLRIReferenceImpl<Object>(PropertyType.Inspectable, (Object)obj);
272             if (type == typeof(RuntimeType))
273             {   // If the type is System.RuntimeType, we want to use System.Type marshaler (it's parent of the type)
274                 return new CLRIReferenceImpl<Type>(PropertyType.Other, (Type)obj);
275             }
276
277             // Handle arbitrary WinRT-compatible value types, and recognize a few special types.
278             PropertyType? propType = null;
279             if (type == s_pointType)
280             {
281                 propType = PropertyType.Point;
282             }
283             else if (type == s_rectType)
284             {
285                 propType = PropertyType.Rect;
286             }
287             else if (type == s_sizeType)
288             {
289                 propType = PropertyType.Size;
290             }
291             else if (type.IsValueType || obj is Delegate)
292             {
293                 propType = PropertyType.Other;
294             }
295
296             if (propType.HasValue)
297             {
298                 Type specificType = typeof(CLRIReferenceImpl<>).MakeGenericType(type);
299                 return Activator.CreateInstance(specificType, new Object[] { propType.Value, obj });
300             }
301
302             Debug.Fail("We should not see non-WinRT type here");
303             return null;
304         }
305
306         internal static Object CreateIReferenceArray(Array obj)
307         {
308             Debug.Assert(obj != null);
309             Debug.Assert(obj.GetType().IsArray);
310
311             Type type = obj.GetType().GetElementType();
312
313             Debug.Assert(obj.Rank == 1 && obj.GetLowerBound(0) == 0 && !type.IsArray);
314
315             if (type == typeof(int))
316                 return new CLRIReferenceArrayImpl<int>(PropertyType.Int32Array, (int[])obj);
317             if (type == typeof(String))
318                 return new CLRIReferenceArrayImpl<String>(PropertyType.StringArray, (String[])obj);
319             if (type == typeof(byte))
320                 return new CLRIReferenceArrayImpl<byte>(PropertyType.UInt8Array, (byte[])obj);
321             if (type == typeof(short))
322                 return new CLRIReferenceArrayImpl<short>(PropertyType.Int16Array, (short[])obj);
323             if (type == typeof(ushort))
324                 return new CLRIReferenceArrayImpl<ushort>(PropertyType.UInt16Array, (ushort[])obj);
325             if (type == typeof(uint))
326                 return new CLRIReferenceArrayImpl<uint>(PropertyType.UInt32Array, (uint[])obj);
327             if (type == typeof(long))
328                 return new CLRIReferenceArrayImpl<long>(PropertyType.Int64Array, (long[])obj);
329             if (type == typeof(ulong))
330                 return new CLRIReferenceArrayImpl<ulong>(PropertyType.UInt64Array, (ulong[])obj);
331             if (type == typeof(float))
332                 return new CLRIReferenceArrayImpl<float>(PropertyType.SingleArray, (float[])obj);
333             if (type == typeof(double))
334                 return new CLRIReferenceArrayImpl<double>(PropertyType.DoubleArray, (double[])obj);
335             if (type == typeof(char))
336                 return new CLRIReferenceArrayImpl<char>(PropertyType.Char16Array, (char[])obj);
337             if (type == typeof(bool))
338                 return new CLRIReferenceArrayImpl<bool>(PropertyType.BooleanArray, (bool[])obj);
339             if (type == typeof(Guid))
340                 return new CLRIReferenceArrayImpl<Guid>(PropertyType.GuidArray, (Guid[])obj);
341             if (type == typeof(DateTimeOffset))
342                 return new CLRIReferenceArrayImpl<DateTimeOffset>(PropertyType.DateTimeArray, (DateTimeOffset[])obj);
343             if (type == typeof(TimeSpan))
344                 return new CLRIReferenceArrayImpl<TimeSpan>(PropertyType.TimeSpanArray, (TimeSpan[])obj);
345             if (type == typeof(Type))
346             {   // Note: The array type will be System.Type, not System.RuntimeType
347                 return new CLRIReferenceArrayImpl<Type>(PropertyType.OtherArray, (Type[])obj);
348             }
349
350             PropertyType? propType = null;
351             if (type == s_pointType)
352             {
353                 propType = PropertyType.PointArray;
354             }
355             else if (type == s_rectType)
356             {
357                 propType = PropertyType.RectArray;
358             }
359             else if (type == s_sizeType)
360             {
361                 propType = PropertyType.SizeArray;
362             }
363             else if (type.IsValueType)
364             {
365                 // note that KeyValuePair`2 is a reference type on the WinRT side so the array
366                 // must be wrapped with CLRIReferenceArrayImpl<Object>
367                 if (type.IsGenericType &&
368                     type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>))
369                 {
370                     Object[] objArray = new Object[obj.Length];
371                     for (int i = 0; i < objArray.Length; i++)
372                     {
373                         objArray[i] = obj.GetValue(i);
374                     }
375                     obj = objArray;
376                 }
377                 else
378                 {
379                     propType = PropertyType.OtherArray;
380                 }
381             }
382             else if (typeof(Delegate).IsAssignableFrom(type))
383             {
384                 propType = PropertyType.OtherArray;
385             }
386
387
388             if (propType.HasValue)
389             {
390                 // All WinRT value type will be Property.Other
391                 Type specificType = typeof(CLRIReferenceArrayImpl<>).MakeGenericType(type);
392                 return Activator.CreateInstance(specificType, new Object[] { propType.Value, obj });
393             }
394             else
395             {
396                 // All WinRT reference type (including arbitary managed type) will be PropertyType.ObjectArray
397                 return new CLRIReferenceArrayImpl<Object>(PropertyType.InspectableArray, (Object[])obj);
398             }
399         }
400     }
401 }