// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using SharpDX.Direct3D;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using SharpDX.Text;
using SharpDX.Mathematics.Interop;
namespace SharpDX
{
///
/// A Delegate to get a property value from an object.
///
/// Type of the getter.
/// The obj to get the property from.
/// The value to get.
public delegate void GetValueFastDelegate(object obj, out T value);
///
/// A Delegate to set a property value to an object.
///
/// Type of the setter.
/// The obj to set the property from.
/// The value to set.
public delegate void SetValueFastDelegate(object obj, ref T value);
///
/// Utility class.
///
public static class Utilities
{
/////
///// Native memcpy.
/////
///// The destination memory location.
///// The source memory location.
///// The count.
/////
//[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl,
// SetLastError = false), SuppressUnmanagedCodeSecurity]
//public static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy);
///
/// Native memcpy.
///
/// The destination memory location.
/// The source memory location.
/// The byte count.
public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy)
{
unsafe
{
// TODO plug in Interop a pluggable CopyMemory using cpblk or memcpy based on architecture
Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy);
}
}
///
/// Compares two block of memory.
///
/// The pointer to compare from.
/// The pointer to compare against.
/// The size in bytes to compare.
/// true if the buffers are equivalent; otherwise, false.
public unsafe static bool CompareMemory(IntPtr from, IntPtr against, int sizeToCompare)
{
var pSrc = (byte*)@from;
var pDst = (byte*)against;
// Compare 8 bytes.
int numberOf = sizeToCompare >> 3;
while (numberOf > 0)
{
if (*(long*)pSrc != *(long*)pDst)
return false;
pSrc += 8;
pDst += 8;
numberOf--;
}
// Compare remaining bytes.
numberOf = sizeToCompare & 7;
while (numberOf > 0)
{
if (*pSrc != *pDst)
return false;
pSrc++;
pDst++;
numberOf--;
}
return true;
}
///
/// Clears the memory.
///
/// The dest.
/// The value.
/// The size in bytes to clear.
public static void ClearMemory(IntPtr dest, byte value, int sizeInBytesToClear)
{
unsafe
{
Interop.memset((void*)dest, value, sizeInBytesToClear);
}
}
///
/// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too.
///
/// A struct to evaluate.
/// Size of this struct.
public static int SizeOf() where T : struct
{
return Interop.SizeOf();
}
///
/// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too.
///
/// A struct.
/// The array of struct to evaluate.
/// Size in bytes of this array of struct.
public static int SizeOf(T[] array) where T : struct
{
return array == null ? 0 : array.Length * Interop.SizeOf();
}
///
/// Pins the specified source and call an action with the pinned pointer.
///
/// The type of the structure to pin.
/// The source.
/// The pin action to perform on the pinned pointer.
public static void Pin(ref T source, Action pinAction) where T : struct
{
unsafe
{
pinAction((IntPtr)Interop.Fixed(ref source));
}
}
///
/// Pins the specified source and call an action with the pinned pointer.
///
/// The type of the structure to pin.
/// The source array.
/// The pin action to perform on the pinned pointer.
public static void Pin(T[] source, Action pinAction) where T : struct
{
unsafe
{
pinAction(source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed(source));
}
}
///
/// Converts a structured array to an equivalent byte array.
///
/// The type of source array.
/// The source array.
/// Converted byte array.
public static byte[] ToByteArray(T[] source) where T : struct
{
if (source == null) return null;
var buffer = new byte[SizeOf() * source.Length];
if (source.Length == 0)
return buffer;
unsafe
{
fixed (void* pBuffer = buffer)
Interop.Write(pBuffer, source, 0, source.Length);
}
return buffer;
}
///
/// Swaps the value between two references.
///
/// Type of a data to swap.
/// The left value.
/// The right value.
public static void Swap(ref T left, ref T right)
{
var temp = left;
left = right;
right = temp;
}
///
/// Reads the specified T data from a memory location.
///
/// Type of a data to read.
/// Memory location to read from.
/// The data read from the memory location.
public static T Read(IntPtr source) where T : struct
{
unsafe
{
return Interop.ReadInline((void*)source);
}
}
///
/// Reads the specified T data from a memory location.
///
/// Type of a data to read.
/// Memory location to read from.
/// The data write to.
/// source pointer + sizeof(T).
public static void Read(IntPtr source, ref T data) where T : struct
{
unsafe
{
Interop.CopyInline(ref data, (void*)source);
}
}
///
/// Reads the specified T data from a memory location.
///
/// Type of a data to read.
/// Memory location to read from.
/// The data write to.
/// source pointer + sizeof(T).
public static void ReadOut(IntPtr source, out T data) where T : struct
{
unsafe
{
Interop.CopyInlineOut(out data, (void*)source);
}
}
///
/// Reads the specified T data from a memory location.
///
/// Type of a data to read.
/// Memory location to read from.
/// The data write to.
/// source pointer + sizeof(T).
public static IntPtr ReadAndPosition(IntPtr source, ref T data) where T : struct
{
unsafe
{
return (IntPtr)Interop.Read((void*)source, ref data);
}
}
///
/// Reads the specified array T[] data from a memory location.
///
/// Type of a data to read.
/// Memory location to read from.
/// The data write to.
/// The offset in the array to write to.
/// The number of T element to read from the memory location.
/// source pointer + sizeof(T) * count.
public static IntPtr Read(IntPtr source, T[] data, int offset, int count) where T : struct
{
unsafe
{
return (IntPtr)Interop.Read((void*)source, data, offset, count);
}
}
///
/// Writes the specified T data to a memory location.
///
/// Type of a data to write.
/// Memory location to write to.
/// The data to write.
/// destination pointer + sizeof(T).
public static void Write(IntPtr destination, ref T data) where T : struct
{
unsafe
{
Interop.CopyInline((void*)destination, ref data);
}
}
///
/// Writes the specified T data to a memory location.
///
/// Type of a data to write.
/// Memory location to write to.
/// The data to write.
/// destination pointer + sizeof(T).
public static IntPtr WriteAndPosition(IntPtr destination, ref T data) where T : struct
{
unsafe
{
return (IntPtr)Interop.Write((void*)destination, ref data);
}
}
///
/// Writes the specified array T[] data to a memory location.
///
/// Type of a data to write.
/// Memory location to write to.
/// The array of T data to write.
/// The offset in the array to read from.
/// The number of T element to write to the memory location.
/// destination pointer + sizeof(T) * count.
public static IntPtr Write(IntPtr destination, T[] data, int offset, int count) where T : struct
{
unsafe
{
return (IntPtr)Interop.Write((void*)destination, data, offset, count);
}
}
///
/// Converts bool array to integer pointers array.
///
/// The bool array.
/// The destination array of int pointers.
public unsafe static void ConvertToIntArray(bool[] array, int* dest)
{
for (int i = 0; i < array.Length; i++)
dest[i] = array[i] ? 1 : 0;
}
///
/// Converts bool array to array.
///
/// The bool array.
/// Converted array of .
public static RawBool[] ConvertToIntArray(bool[] array)
{
var temp = new RawBool[array.Length];
for (int i = 0; i < temp.Length; i++)
temp[i] = array[i];
return temp;
}
///
/// Converts integer pointer array to bool array.
///
/// The array of integer pointers.
/// Array size.
/// Converted array of bool.
public static unsafe bool[] ConvertToBoolArray(int* array, int length)
{
var temp = new bool[length];
for(int i = 0; i < temp.Length; i++)
temp[i] = array[i] != 0;
return temp;
}
///
/// Converts array to bool array.
///
/// The array.
/// Converted array of bool.
public static bool[] ConvertToBoolArray(RawBool[] array)
{
var temp = new bool[array.Length];
for(int i = 0; i < temp.Length; i++)
temp[i] = array[i];
return temp;
}
///
/// Gets the from a type.
///
/// The type.
/// The guid associated with this type.
public static Guid GetGuidFromType(Type type)
{
return type.GetTypeInfo().GUID;
}
///
/// Determines whether a given type inherits from a generic type.
///
/// Type of the class to check if it inherits from generic type.
/// Type of the generic.
/// true if [is assignable to generic type] [the specified given type]; otherwise, false.
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
// from http://stackoverflow.com/a/1075059/1356325
#if BEFORE_NET45
var interfaceTypes = givenType.GetTypeInfo().GetInterfaces();
#else
var interfaceTypes = givenType.GetTypeInfo().ImplementedInterfaces;
#endif
foreach (var it in interfaceTypes)
{
if (it.GetTypeInfo().IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.GetTypeInfo().IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.GetTypeInfo().BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
///
/// Allocate an aligned memory buffer.
///
/// Size of the buffer to allocate.
/// Alignment, 16 bytes by default.
/// A pointer to a buffer aligned.
///
/// To free this buffer, call .
///
public unsafe static IntPtr AllocateMemory(int sizeInBytes, int align = 16)
{
int mask = align - 1;
var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + IntPtr.Size);
var ptr = (long)((byte*)memPtr + sizeof(void*) + mask) & ~mask;
((IntPtr*)ptr)[-1] = memPtr;
return new IntPtr((void*)ptr);
}
///
/// Allocate an aligned memory buffer and clear it with a specified value (0 by default).
///
/// Size of the buffer to allocate.
/// Default value used to clear the buffer.
/// Alignment, 16 bytes by default.
/// A pointer to a buffer aligned.
///
/// To free this buffer, call .
///
public static IntPtr AllocateClearedMemory(int sizeInBytes, byte clearValue = 0, int align = 16)
{
var ptr = AllocateMemory(sizeInBytes, align);
ClearMemory(ptr, clearValue, sizeInBytes);
return ptr;
}
///
/// Determines whether the specified memory pointer is aligned in memory.
///
/// The memory pointer.
/// The align.
/// true if the specified memory pointer is aligned in memory; otherwise, false.
public static bool IsMemoryAligned(IntPtr memoryPtr, int align = 16)
{
return ((memoryPtr.ToInt64() & (align-1)) == 0);
}
///
/// Allocate an aligned memory buffer.
///
/// A pointer to a buffer aligned.
///
/// The buffer must have been allocated with .
///
public unsafe static void FreeMemory(IntPtr alignedBuffer)
{
if (alignedBuffer == IntPtr.Zero) return;
Marshal.FreeHGlobal(((IntPtr*) alignedBuffer)[-1]);
}
///
/// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string.
///
/// The pointer to an ANSI null string.
/// Maximum length of the string.
/// The converted string.
public static string PtrToStringAnsi(IntPtr pointer, int maxLength)
{
string managedString = Marshal.PtrToStringAnsi(pointer); // copy null-terminating unmanaged text from pointer to a managed string
if (managedString != null && managedString.Length > maxLength)
managedString = managedString.Substring(0, maxLength);
return managedString;
}
///
/// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string.
///
/// The pointer to an Unicode null string.
/// Maximum length of the string.
/// The converted string.
public static string PtrToStringUni(IntPtr pointer, int maxLength)
{
string managedString = Marshal.PtrToStringUni(pointer); // copy null-terminating unmanaged text from pointer to a managed string
if (managedString != null && managedString.Length > maxLength)
managedString = managedString.Substring(0, maxLength);
return managedString;
}
///
/// Copies the contents of a managed String into unmanaged memory, converting into ANSI format as it copies.
///
/// A managed string to be copied.
/// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null.
public static unsafe IntPtr StringToHGlobalAnsi(string s)
{
return Marshal.StringToHGlobalAnsi(s);
}
///
/// Copies the contents of a managed String into unmanaged memory.
///
/// A managed string to be copied.
/// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null.
public static unsafe IntPtr StringToHGlobalUni(string s)
{
return Marshal.StringToHGlobalUni(s);
}
///
/// Copies the contents of a managed String into unmanaged memory using
///
/// A managed string to be copied.
/// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null.
public static unsafe IntPtr StringToCoTaskMemUni(string s)
{
if (s == null)
{
return IntPtr.Zero;
}
int num = (s.Length + 1) * 2;
if (num < s.Length)
{
throw new ArgumentOutOfRangeException("s");
}
IntPtr ptr2 = Marshal.AllocCoTaskMem(num);
if (ptr2 == IntPtr.Zero)
{
throw new OutOfMemoryException();
}
CopyStringToUnmanaged(ptr2, s);
return ptr2;
}
private unsafe static void CopyStringToUnmanaged(IntPtr ptr, string str)
{
fixed (char* pStr = str)
{
CopyMemory(ptr, new IntPtr(pStr), (str.Length + 1 ) * 2);
}
}
///
/// Gets the IUnknown from object. Similar to but accept null object
/// by returning an IntPtr.Zero IUnknown pointer.
///
/// The managed object.
/// An IUnknown pointer to a managed object.
public static IntPtr GetIUnknownForObject(object obj)
{
IntPtr objPtr = obj == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(obj);
//if (obj is ComObject && ((ComObject)obj).NativePointer == IntPtr.Zero)
// (((ComObject)obj).NativePointer) = objPtr;
return objPtr;
}
///
/// Gets an object from an IUnknown pointer. Similar to but accept IntPtr.Zero
/// by returning a null object.
///
/// an IUnknown pointer to a managed object.
/// The managed object.
public static object GetObjectForIUnknown(IntPtr iunknownPtr)
{
return iunknownPtr == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(iunknownPtr);
}
///
/// String helper join method to display an array of object as a single string.
///
/// The separator.
/// The array.
/// A string with array elements separated by the separator.
public static string Join(string separator, T[] array)
{
var text = new StringBuilder();
if (array != null)
{
for (int i = 0; i < array.Length; i++)
{
if (i > 0) text.Append(separator);
text.Append(array[i]);
}
}
return text.ToString();
}
///
/// String helper join method to display an enumerable of object as a single string.
///
/// The separator.
/// The enumerable.
/// A string with array elements separated by the separator.
public static string Join(string separator, IEnumerable elements)
{
var elementList = new List();
foreach (var element in elements)
elementList.Add(element.ToString());
var text = new StringBuilder();
for (int i = 0; i < elementList.Count; i++)
{
var element = elementList[i];
if (i > 0) text.Append(separator);
text.Append(element);
}
return text.ToString();
}
///
/// String helper join method to display an enumerable of object as a single string.
///
/// The separator.
/// The enumerable.
/// A string with array elements separated by the separator.
public static string Join(string separator, IEnumerator elements)
{
var elementList = new List();
while (elements.MoveNext())
elementList.Add(elements.Current.ToString());
var text = new StringBuilder();
for (int i = 0; i < elementList.Count; i++)
{
var element = elementList[i];
if (i > 0) text.Append(separator);
text.Append(element);
}
return text.ToString();
}
///
/// Converts a blob to a string.
///
/// A blob.
/// A string extracted from a blob.
public static string BlobToString(Blob blob)
{
if (blob == null) return null;
string output;
output = Marshal.PtrToStringAnsi(blob.BufferPointer);
blob.Dispose();
return output;
}
///
/// Equivalent to IntPtr.Add method from 3.5+ .NET Framework.
/// Adds an offset to the value of a pointer.
///
/// A native pointer.
/// The offset to add (number of bytes).
/// A new pointer that reflects the addition of offset to pointer.
public unsafe static IntPtr IntPtrAdd(IntPtr ptr, int offset)
{
return new IntPtr(((byte*) ptr) + offset);
}
///
/// Read stream to a byte[] buffer.
///
/// Input stream.
/// A byte[] buffer.
public static byte[] ReadStream(Stream stream)
{
int readLength = 0;
return ReadStream(stream, ref readLength);
}
///
/// Read stream to a byte[] buffer.
///
/// Input stream.
/// Length to read.
/// A byte[] buffer.
public static byte[] ReadStream(Stream stream, ref int readLength)
{
Debug.Assert(stream != null);
Debug.Assert(stream.CanRead);
int num = readLength;
Debug.Assert(num <= (stream.Length - stream.Position));
if (num == 0)
readLength = (int) (stream.Length - stream.Position);
num = readLength;
Debug.Assert(num >= 0);
if (num == 0)
return new byte[0];
byte[] buffer = new byte[num];
int bytesRead = 0;
if (num > 0)
{
do
{
bytesRead += stream.Read(buffer, bytesRead, readLength - bytesRead);
} while (bytesRead < readLength);
}
return buffer;
}
///
/// Compares two collection, element by elements.
///
/// A "from" enumerator.
/// A "to" enumerator.
/// true if lists are identical, false otherwise.
public static bool Compare(IEnumerable left, IEnumerable right)
{
if (ReferenceEquals(left, right))
return true;
if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
return false;
return Compare(left.GetEnumerator(), right.GetEnumerator());
}
///
/// Compares two collection, element by elements.
///
/// A "from" enumerator.
/// A "to" enumerator.
/// true if lists are identical; otherwise, false.
public static bool Compare(IEnumerator leftIt, IEnumerator rightIt)
{
if (ReferenceEquals(leftIt, rightIt))
return true;
if (ReferenceEquals(leftIt, null) || ReferenceEquals(rightIt, null))
return false;
bool hasLeftNext;
bool hasRightNext;
while (true)
{
hasLeftNext = leftIt.MoveNext();
hasRightNext = rightIt.MoveNext();
if (!hasLeftNext || !hasRightNext)
break;
if (!Equals(leftIt.Current, rightIt.Current))
return false;
}
// If there is any left element
if (hasLeftNext != hasRightNext)
return false;
return true;
}
///
/// Compares two collection, element by elements.
///
/// The collection to compare from.
/// The collection to compare to.
/// true if lists are identical (but not necessarily of the same time); otherwise , false.
public static bool Compare(ICollection left, ICollection right)
{
if (ReferenceEquals(left, right))
return true;
if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
return false;
if (left.Count != right.Count)
return false;
int count = 0;
var leftIt = left.GetEnumerator();
var rightIt = right.GetEnumerator();
while (leftIt.MoveNext() && rightIt.MoveNext())
{
if (!Equals(leftIt.Current, rightIt.Current))
return false;
count++;
}
// Just double check to make sure that the iterator actually returns
// the exact number of elements
if (count != left.Count)
return false;
return true;
}
///
/// Gets the custom attribute.
///
/// Type of the custom attribute.
/// The member info.
/// if set to true [inherited].
/// The custom attribute or null if not found.
public static T GetCustomAttribute(MemberInfo memberInfo, bool inherited = false) where T : Attribute
{
return memberInfo.GetCustomAttribute(inherited);
}
///
/// Gets the custom attributes.
///
/// Type of the custom attribute.
/// The member info.
/// if set to true [inherited].
/// The custom attribute or null if not found.
public static IEnumerable GetCustomAttributes(MemberInfo memberInfo, bool inherited = false) where T : Attribute
{
return memberInfo.GetCustomAttributes(inherited);
}
///
/// Determines whether fromType can be assigned to toType.
///
/// To type.
/// From type.
///
/// true if [is assignable from] [the specified to type]; otherwise, false.
///
public static bool IsAssignableFrom(Type toType, Type fromType)
{
return toType.GetTypeInfo().IsAssignableFrom(fromType.GetTypeInfo());
}
///
/// Determines whether the specified type to test is an enum.
///
/// The type to test.
///
/// true if the specified type to test is an enum; otherwise, false.
///
public static bool IsEnum(Type typeToTest)
{
return typeToTest.GetTypeInfo().IsEnum;
}
///
/// Determines whether the specified type to test is a value type.
///
/// The type to test.
///
/// true if the specified type to test is a value type; otherwise, false.
///
public static bool IsValueType(Type typeToTest)
{
return typeToTest.GetTypeInfo().IsValueType;
}
private static MethodInfo GetMethod(Type type, string name, Type[] typeArgs) {
#if BEFORE_NET45
foreach( var method in type.GetTypeInfo().GetMethods(BindingFlags.Public|BindingFlags.Instance))
{
if(method.Name != name)
{
continue;
}
#else
foreach( var method in type.GetTypeInfo().GetDeclaredMethods(name))
{
#endif
if ( method.GetParameters().Length == typeArgs.Length) {
var parameters = method.GetParameters();
bool methodFound = true;
for (int i = 0; i < typeArgs.Length; i++)
{
if (parameters[i].ParameterType != typeArgs[i]) {
methodFound = false;
break;
}
}
if (methodFound) {
return method;
}
}
}
return null;
}
///
/// Builds a fast property getter from a type and a property info.
///
/// Type of the getter.
/// Type of the custom effect.
/// The property info to get the value from.
/// A compiled delegate.
public static GetValueFastDelegate BuildPropertyGetter(Type customEffectType, PropertyInfo propertyInfo)
{
var valueParam = Expression.Parameter(typeof(T).MakeByRefType());
var objectParam = Expression.Parameter(typeof(object));
var castParam = Expression.Convert(objectParam, customEffectType);
var propertyAccessor = Expression.Property(castParam, propertyInfo);
Expression convertExpression;
if (propertyInfo.PropertyType == typeof(bool))
{
// Convert bool to int: effect.Property ? 1 : 0
convertExpression = Expression.Condition(propertyAccessor, Expression.Constant(1), Expression.Constant(0));
}
else
{
convertExpression = Expression.Convert(propertyAccessor, typeof(T));
}
return Expression.Lambda>(Expression.Assign(valueParam, convertExpression), objectParam, valueParam).Compile();
}
///
/// Builds a fast property setter from a type and a property info.
///
/// Type of the setter.
/// Type of the custom effect.
/// The property info to set the value to.
/// A compiled delegate.
public static SetValueFastDelegate BuildPropertySetter(Type customEffectType, PropertyInfo propertyInfo)
{
var valueParam = Expression.Parameter(typeof(T).MakeByRefType());
var objectParam = Expression.Parameter(typeof(object));
var castParam = Expression.Convert(objectParam, customEffectType);
var propertyAccessor = Expression.Property(castParam, propertyInfo);
Expression convertExpression;
if (propertyInfo.PropertyType == typeof(bool))
{
// Convert int to bool: value != 0
convertExpression = Expression.NotEqual(valueParam, Expression.Constant(0));
}
else
{
convertExpression = Expression.Convert(valueParam, propertyInfo.PropertyType);
}
return Expression.Lambda>(Expression.Assign(propertyAccessor, convertExpression), objectParam, valueParam).Compile();
}
///
/// Finds an explicit conversion between a source type and a target type.
///
/// Type of the source.
/// Type of the target.
/// The method to perform the conversion. null if not found.
private static MethodInfo FindExplicitConverstion(Type sourceType, Type targetType)
{
// No need for cast for similar source and target type
if (sourceType == targetType)
return null;
var methods = new List();
var tempType = sourceType;
while (tempType != null)
{
#if BEFORE_NET45
methods.AddRange(tempType.GetTypeInfo().GetMethods(BindingFlags.Public)); //target methods will be favored in the search
#else
methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search
#endif
tempType = tempType.GetTypeInfo().BaseType;
}
tempType = targetType;
while (tempType != null)
{
#if BEFORE_NET45
methods.AddRange(tempType.GetTypeInfo().GetMethods(BindingFlags.Public)); //target methods will be favored in the search
#else
methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search
#endif
tempType = tempType.GetTypeInfo().BaseType;
}
foreach (MethodInfo mi in methods)
{
if (mi.Name == "op_Explicit") //will return target and take one parameter
if (mi.ReturnType == targetType)
if (IsAssignableFrom(mi.GetParameters()[0].ParameterType, sourceType))
return mi;
}
return null;
}
[Flags]
public enum CLSCTX : uint
{
ClsctxInprocServer = 0x1,
ClsctxInprocHandler = 0x2,
ClsctxLocalServer = 0x4,
ClsctxInprocServer16 = 0x8,
ClsctxRemoteServer = 0x10,
ClsctxInprocHandler16 = 0x20,
ClsctxReserved1 = 0x40,
ClsctxReserved2 = 0x80,
ClsctxReserved3 = 0x100,
ClsctxReserved4 = 0x200,
ClsctxNoCodeDownload = 0x400,
ClsctxReserved5 = 0x800,
ClsctxNoCustomMarshal = 0x1000,
ClsctxEnableCodeDownload = 0x2000,
ClsctxNoFailureLog = 0x4000,
ClsctxDisableAaa = 0x8000,
ClsctxEnableAaa = 0x10000,
ClsctxFromDefaultContext = 0x20000,
ClsctxInproc = ClsctxInprocServer | ClsctxInprocHandler,
ClsctxServer = ClsctxInprocServer | ClsctxLocalServer | ClsctxRemoteServer,
ClsctxAll = ClsctxServer | ClsctxInprocHandler
}
#if WINDOWS_UWP
[StructLayout(LayoutKind.Sequential)]
public struct MultiQueryInterface
{
public IntPtr InterfaceIID;
public IntPtr IUnknownPointer;
public Result ResultCode;
};
[DllImport("api-ms-win-core-com-l1-1-0.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)]
private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
IntPtr pUnkOuter,
CLSCTX dwClsContext,
IntPtr reserved,
int countMultiQuery,
ref MultiQueryInterface query);
internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject)
{
MultiQueryInterface localQuery = new MultiQueryInterface()
{
InterfaceIID = new IntPtr(&riid),
IUnknownPointer = IntPtr.Zero,
ResultCode = 0,
};
var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery);
result.CheckError();
localQuery.ResultCode.CheckError();
comObject.NativePointer = localQuery.IUnknownPointer;
}
internal unsafe static bool TryCreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject)
{
MultiQueryInterface localQuery = new MultiQueryInterface()
{
InterfaceIID = new IntPtr(&riid),
IUnknownPointer = IntPtr.Zero,
ResultCode = 0,
};
var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery);
comObject.NativePointer = localQuery.IUnknownPointer;
return result.Success && localQuery.ResultCode.Success;
}
#else
[DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstance", PreserveSig = true)]
private static extern Result CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pUnkOuter, CLSCTX dwClsContext, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr comObject);
internal static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject)
{
IntPtr pointer;
var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer);
result.CheckError();
comObject.NativePointer = pointer;
}
internal static bool TryCreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject)
{
IntPtr pointer;
var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer);
comObject.NativePointer = pointer;
return result.Success;
}
#endif
/// Determines the concurrency model used for incoming calls to objects created by this thread. This concurrency model can be either apartment-threaded or multi-threaded.
public enum CoInit
{
///
/// Initializes the thread for apartment-threaded object concurrency.
///
MultiThreaded = 0x0,
///
/// Initializes the thread for multi-threaded object concurrency.
///
ApartmentThreaded = 0x2,
///
/// Disables DDE for OLE1 support.
///
DisableOle1Dde = 0x4,
///
/// Trade memory for speed.
///
SpeedOverMemory = 0x8
}
#if WINDOWS_UWP
[DllImport("api-ms-win-core-handle-l1-1-0.dll", EntryPoint = "CloseHandle", SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle);
#else
[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle);
#endif
///
/// Gets the proc address of a DLL.
///
/// The handle.
/// The DLL function to import.
/// If the function was not found.
/// Pointer to address of the exported function or variable.
public static IntPtr GetProcAddress(IntPtr handle, string dllFunctionToImport)
{
IntPtr result = GetProcAddress_(handle, dllFunctionToImport);
if (result == IntPtr.Zero)
throw new SharpDXException(dllFunctionToImport);
return result;
}
#if WINDOWS_UWP
[DllImport("api-ms-win-core-libraryloader-l1-1-1.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress_(IntPtr hModule, string procName);
#else
// http://www.pinvoke.net/default.aspx/kernel32.getprocaddress
// http://stackoverflow.com/questions/3754264/c-sharp-getprocaddress-returns-zero
[DllImport("kernel32", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress_(IntPtr hModule, string procName);
#endif
///
/// Compute a FNV1-modified Hash from Fowler/Noll/Vo Hash improved version.
///
/// Data to compute the hash from.
/// A hash value.
public static int ComputeHashFNVModified(byte[] data)
{
const uint p = 16777619;
uint hash = 2166136261;
foreach (byte b in data)
hash = (hash ^ b) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return unchecked((int)hash);
}
///
/// Safely dispose a reference if not null, and set it to null after dispose.
///
/// The type of COM interface to dispose.
/// Object to dispose.
///
/// The reference will be set to null after dispose.
///
public static void Dispose(ref T comObject) where T : class, IDisposable
{
if (comObject != null)
{
comObject.Dispose();
comObject = null;
}
}
///
/// Transforms an to an array of T.
///
/// Type of the element
/// The enumerable source.
/// an array of T
public static T[] ToArray(IEnumerable source)
{
return new Buffer(source).ToArray();
}
///
/// Test if there is an element in this enumeration.
///
/// Type of the element
/// The enumerable source.
/// true if there is an element in this enumeration, false otherwise
public static bool Any(IEnumerable source)
{
return source.GetEnumerator().MoveNext();
}
///
/// Select elements from an enumeration.
///
/// The type of the T source.
/// The type of the T result.
/// The source.
/// The selector.
/// A enumeration of selected values
public static IEnumerable SelectMany(IEnumerable source, Func> selector)
{
foreach (TSource sourceItem in source)
{
foreach (TResult result in selector(sourceItem))
yield return result;
}
}
///
/// Selects distinct elements from an enumeration.
///
/// The type of the T source.
/// The source.
/// The comparer.
/// A enumeration of selected values
public static IEnumerable Distinct(IEnumerable source, IEqualityComparer comparer = null)
{
if (comparer == null)
comparer = EqualityComparer.Default;
// using Dictionary is not really efficient but easy to implement
var values = new Dictionary(comparer);
foreach (TSource sourceItem in source)
{
if (!values.ContainsKey(sourceItem))
{
values.Add(sourceItem, null);
yield return sourceItem;
}
}
}
internal struct Buffer
{
internal TElement[] items;
internal int count;
internal Buffer(IEnumerable source)
{
var array = (TElement[])null;
int length = 0;
var collection = source as ICollection;
if (collection != null)
{
length = collection.Count;
if (length > 0)
{
array = new TElement[length];
collection.CopyTo(array, 0);
}
}
else
{
foreach (TElement element in source)
{
if (array == null)
array = new TElement[4];
else if (array.Length == length)
{
var elementArray = new TElement[checked(length * 2)];
Array.Copy(array, 0, elementArray, 0, length);
array = elementArray;
}
array[length] = element;
++length;
}
}
items = array;
count = length;
}
internal TElement[] ToArray()
{
if (count == 0)
return new TElement[0];
if (items.Length == count)
return items;
var elementArray = new TElement[count];
Array.Copy(items, 0, elementArray, 0, count);
return elementArray;
}
}
///
/// Determines whether the type inherits from the specified type (used to determine a type without using an explicit type instance).
///
/// The type.
/// Name of the parent type to find in inheritance hierarchy of type.
/// true if the type inherits from the specified type; otherwise, false.
public static bool IsTypeInheritFrom(Type type, string parentType)
{
while (type != null)
{
if (type.FullName == parentType)
{
return true;
}
type = type.GetTypeInfo().BaseType;
}
return false;
}
}
}