|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: OAVariantLib
**
**
** Purpose: This class only exists to provide support for
** implenting IDispatch on managed objects. It is
** used to provide OleAut style coercion rules.
**
**
===========================================================*/
namespace Microsoft.Win32 {
using System;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using CultureInfo = System.Globalization.CultureInfo;
internal static class OAVariantLib
{
#region Constants
// Constants for VariantChangeType from OleAuto.h
public const int NoValueProp = 0x01;
public const int AlphaBool = 0x02;
public const int NoUserOverride = 0x04;
public const int CalendarHijri = 0x08;
public const int LocalBool = 0x10;
internal static readonly Type [] ClassTypes = {
typeof(Empty),
typeof(void),
typeof(Boolean),
typeof(Char),
typeof(SByte),
typeof(Byte),
typeof(Int16),
typeof(UInt16),
typeof(Int32),
typeof(UInt32),
typeof(Int64),
typeof(UInt64),
typeof(Single),
typeof(Double),
typeof(String),
typeof(void),
typeof(DateTime),
typeof(TimeSpan),
typeof(Object),
typeof(Decimal),
null, // Enums - what do we do here?
typeof(Missing),
typeof(DBNull),
};
// Keep these numbers in sync w/ the above array.
private const int CV_OBJECT=0x12;
#endregion
#region Internal Methods
/**
* Changes a Variant from one type to another, calling the OLE
* Automation VariantChangeTypeEx routine. Note the legal types here are
* restricted to the subset of what can be legally found in a VB
* Variant and the types that CLR supports explicitly in the
* CLR Variant class.
*/
[System.Security.SecurityCritical] // auto-generated
internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture)
{
if (targetClass == null)
throw new ArgumentNullException("targetClass");
if (culture == null)
throw new ArgumentNullException("culture");
Variant result = new Variant ();
ChangeTypeEx(ref result, ref source,
#if FEATURE_USE_LCID
culture.LCID,
#else
// @CORESYSTODO: what does CoreSystem expect for this argument?
0,
#endif
targetClass.TypeHandle.Value, GetCVTypeFromClass(targetClass), options);
return result;
}
#endregion
#region Private Helpers
private static int GetCVTypeFromClass(Type ctype)
{
Contract.Requires(ctype != null);
#if _DEBUG
BCLDebug.Assert(ClassTypes[CV_OBJECT] == typeof(Object), "OAVariantLib::ClassTypes[CV_OBJECT] == Object.class");
#endif
int cvtype=-1;
for (int i=0; i<ClassTypes.Length; i++) {
if (ctype.Equals(ClassTypes[i])) {
cvtype=i;
break;
}
}
// OleAut Binder works better if unrecognized
// types were changed to Object. So don't throw here.
if (cvtype == -1)
cvtype = CV_OBJECT;
return cvtype;
}
#endregion
#region Private FCalls
[System.Security.SecurityCritical] // auto-generated
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ResourceExposure(ResourceScope.None)]
private static extern void ChangeTypeEx(ref Variant result, ref Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);
#endregion
}
}
|