Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace System.Dynamic.Utils {
/// <summary>
/// Provides a dictionary-like object used for caches which holds onto a maximum
/// number of elements specified at construction time.
///
/// This class is not thread safe.
/// </summary>
internal class CacheDict<TKey, TValue> {
private readonly Dictionary<TKey, KeyInfo> _dict = new Dictionary<TKey, KeyInfo>();
private readonly LinkedList<TKey> _list = new LinkedList<TKey>();
private readonly int _maxSize;
/// <summary>
/// Creates a dictionary-like object used for caches.
/// </summary>
/// <param name="maxSize">The maximum number of elements to store.</param>
internal CacheDict(int maxSize) {
_maxSize = maxSize;
}
/// <summary>
/// Tries to get the value associated with 'key', returning true if it's found and
/// false if it's not present.
/// </summary>
internal bool TryGetValue(TKey key, out TValue value) {
KeyInfo storedValue;
if (_dict.TryGetValue(key, out storedValue)) {
LinkedListNode<TKey> node = storedValue.List;
if (node.Previous != null) {
// move us to the head of the list...
_list.Remove(node);
_list.AddFirst(node);
}
value = storedValue.Value;
return true;
}
value = default(TValue);
return false;
}
/// <summary>
/// Adds a new element to the cache, replacing and moving it to the front if the
/// element is already present.
/// </summary>
internal void Add(TKey key, TValue value) {
KeyInfo keyInfo;
if (_dict.TryGetValue(key, out keyInfo)) {
// remove original entry from the linked list
_list.Remove(keyInfo.List);
} else if (_list.Count == _maxSize) {
// we've reached capacity, remove the last used element...
LinkedListNode<TKey> node = _list.Last;
_list.RemoveLast();
bool res = _dict.Remove(node.Value);
Debug.Assert(res);
}
// add the new entry to the head of the list and into the dictionary
LinkedListNode<TKey> listNode = new LinkedListNode<TKey>(key);
_list.AddFirst(listNode);
_dict[key] = new CacheDict<TKey, TValue>.KeyInfo(value, listNode);
}
/// <summary>
/// Returns the value associated with the given key, or throws KeyNotFoundException
/// if the key is not present.
/// </summary>
internal TValue this[TKey key] {
get {
TValue res;
if (TryGetValue(key, out res)) {
return res;
}
throw new KeyNotFoundException();
}
set {
Add(key, value);
}
}
private struct KeyInfo {
internal readonly TValue Value;
internal readonly LinkedListNode<TKey> List;
internal KeyInfo(TValue value, LinkedListNode<TKey> list) {
Value = value;
List = list;
}
}
}
}

View File

@@ -0,0 +1,202 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !FEATURE_CORE_DLR
using Microsoft.Scripting.Utils;
using Microsoft.Scripting.Ast;
#else
using System.Diagnostics.Contracts;
using System.Linq.Expressions;
#endif
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace System.Dynamic.Utils {
internal static class CollectionExtensions {
/// <summary>
/// Wraps the provided enumerable into a ReadOnlyCollection{T}
///
/// Copies all of the data into a new array, so the data can't be
/// changed after creation. The exception is if the enumerable is
/// already a ReadOnlyCollection{T}, in which case we just return it.
/// </summary>
internal static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable) {
if (enumerable == null) {
return EmptyReadOnlyCollection<T>.Instance;
}
#if SILVERLIGHT
if (Expression.SilverlightQuirks) {
// Allow any ReadOnlyCollection to be stored directly
// (even though this is not safe)
var r = enumerable as ReadOnlyCollection<T>;
if (r != null) {
return r;
}
}
#endif
var troc = enumerable as TrueReadOnlyCollection<T>;
if (troc != null) {
return troc;
}
var builder = enumerable as ReadOnlyCollectionBuilder<T>;
if (builder != null) {
return builder.ToReadOnlyCollection();
}
var collection = enumerable as ICollection<T>;
if (collection != null) {
int count = collection.Count;
if (count == 0) {
return EmptyReadOnlyCollection<T>.Instance;
}
T[] clone = new T[count];
collection.CopyTo(clone, 0);
return new TrueReadOnlyCollection<T>(clone);
}
// ToArray trims the excess space and speeds up access
return new TrueReadOnlyCollection<T>(new List<T>(enumerable).ToArray());
}
// We could probably improve the hashing here
internal static int ListHashCode<T>(this IEnumerable<T> list) {
var cmp = EqualityComparer<T>.Default;
int h = 6551;
foreach (T t in list) {
h ^= (h << 5) ^ cmp.GetHashCode(t);
}
return h;
}
internal static bool ListEquals<T>(this ICollection<T> first, ICollection<T> second) {
if (first.Count != second.Count) {
return false;
}
var cmp = EqualityComparer<T>.Default;
var f = first.GetEnumerator();
var s = second.GetEnumerator();
while (f.MoveNext()) {
s.MoveNext();
if (!cmp.Equals(f.Current, s.Current)) {
return false;
}
}
return true;
}
internal static IEnumerable<U> Select<T, U>(this IEnumerable<T> enumerable, Func<T, U> select) {
foreach (T t in enumerable) {
yield return select(t);
}
}
// Name needs to be different so it doesn't conflict with Enumerable.Select
internal static U[] Map<T, U>(this ICollection<T> collection, Func<T, U> select) {
int count = collection.Count;
U[] result = new U[count];
count = 0;
foreach (T t in collection) {
result[count++] = select(t);
}
return result;
}
internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
foreach (T t in enumerable) {
if (where(t)) {
yield return t;
}
}
}
internal static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
foreach (T element in source) {
if (predicate(element)) {
return true;
}
}
return false;
}
internal static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
foreach (T element in source) {
if (!predicate(element)) {
return false;
}
}
return true;
}
internal static T[] RemoveFirst<T>(this T[] array) {
T[] result = new T[array.Length - 1];
Array.Copy(array, 1, result, 0, result.Length);
return result;
}
internal static T[] RemoveLast<T>(this T[] array) {
T[] result = new T[array.Length - 1];
Array.Copy(array, 0, result, 0, result.Length);
return result;
}
internal static T[] AddFirst<T>(this IList<T> list, T item) {
T[] res = new T[list.Count + 1];
res[0] = item;
list.CopyTo(res, 1);
return res;
}
internal static T[] AddLast<T>(this IList<T> list, T item) {
T[] res = new T[list.Count + 1];
list.CopyTo(res, 0);
res[list.Count] = item;
return res;
}
internal static T First<T>(this IEnumerable<T> source) {
var list = source as IList<T>;
if (list != null) {
return list[0];
}
using (var e = source.GetEnumerator()) {
if (e.MoveNext()) return e.Current;
}
throw new InvalidOperationException();
}
internal static T Last<T>(this IList<T> list) {
return list[list.Count - 1];
}
internal static T[] Copy<T>(this T[] array) {
T[] copy = new T[array.Length];
Array.Copy(array, copy, array.Length);
return copy;
}
}
internal static class EmptyReadOnlyCollection<T> {
internal static ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(new T[0]);
}
}

View File

@@ -0,0 +1,97 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !FEATURE_CORE_DLR
using Microsoft.Scripting.Ast;
#else
using System.Linq.Expressions;
#endif
#if SILVERLIGHT
using System.Core;
#endif
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Dynamic.Utils {
// Will be replaced with CLRv4 managed contracts
internal static class ContractUtils {
internal static Exception Unreachable {
get {
Debug.Assert(false, "Unreachable");
return new InvalidOperationException("Code supposed to be unreachable");
}
}
internal static void Requires(bool precondition) {
if (!precondition) {
throw new ArgumentException(Strings.MethodPreconditionViolated);
}
}
internal static void Requires(bool precondition, string paramName) {
Debug.Assert(!string.IsNullOrEmpty(paramName));
if (!precondition) {
throw new ArgumentException(Strings.InvalidArgumentValue, paramName);
}
}
internal static void RequiresNotNull(object value, string paramName) {
Debug.Assert(!string.IsNullOrEmpty(paramName));
if (value == null) {
throw new ArgumentNullException(paramName);
}
}
internal static void RequiresNotEmpty<T>(ICollection<T> collection, string paramName) {
RequiresNotNull(collection, paramName);
if (collection.Count == 0) {
throw new ArgumentException(Strings.NonEmptyCollectionRequired, paramName);
}
}
/// <summary>
/// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
/// </summary>
/// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
internal static void RequiresArrayRange<T>(IList<T> array, int offset, int count, string offsetName, string countName) {
Debug.Assert(!string.IsNullOrEmpty(offsetName));
Debug.Assert(!string.IsNullOrEmpty(countName));
Debug.Assert(array != null);
if (count < 0) throw new ArgumentOutOfRangeException(countName);
if (offset < 0 || array.Count - offset < count) throw new ArgumentOutOfRangeException(offsetName);
}
/// <summary>
/// Requires the array and all its items to be non-null.
/// </summary>
internal static void RequiresNotNullItems<T>(IList<T> array, string arrayName) {
Debug.Assert(arrayName != null);
RequiresNotNull(array, arrayName);
for (int i = 0; i < array.Count; i++) {
if (array[i] == null) {
throw new ArgumentNullException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0}[{1}]", arrayName, i));
}
}
}
}
}

View File

@@ -0,0 +1 @@
5cc9f88a4e5157f0cd248f505456cdeb962121fa

View File

@@ -0,0 +1,10 @@
using System;
namespace System.Runtime.CompilerServices
{
/// <summary>
/// Indicates that a method is an extension method, or that a class or assembly contains extension methods.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
public sealed class ExtensionAttribute : Attribute { }
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !FEATURE_CORE_DLR
using Microsoft.Scripting.Ast;
using Microsoft.Scripting.Utils;
#else
using System.Linq.Expressions;
#endif
using System.Collections.Generic;
namespace System.Dynamic.Utils {
// Miscellaneous helpers that don't belong anywhere else
internal static class Helpers {
internal static T CommonNode<T>(T first, T second, Func<T, T> parent) where T : class {
var cmp = EqualityComparer<T>.Default;
if (cmp.Equals(first, second)) {
return first;
}
var set = new Set<T>(cmp);
for (T t = first; t != null; t = parent(t)) {
set.Add(t);
}
for (T t = second; t != null; t = parent(t)) {
if (set.Contains(t)) {
return t;
}
}
return null;
}
internal static void IncrementCount<T>(T key, Dictionary<T, int> dict) {
int count;
dict.TryGetValue(key, out count);
dict[key] = count + 1;
}
}
}

View File

@@ -0,0 +1,33 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
namespace System.Runtime.CompilerServices {
/// <summary>
/// An interface to represent values of runtime variables.
/// </summary>
public interface IRuntimeVariables {
/// <summary>
/// Count of the variables.
/// </summary>
int Count { get; }
/// <summary>
/// An indexer to get/set the values of the runtime variables.
/// </summary>
/// <param name="index">An index of the runtime variable.</param>
/// <returns>The value of the runtime variable.</returns>
object this[int index] { get; set; }
}
}

View File

@@ -0,0 +1,203 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !FEATURE_CORE_DLR
using Microsoft.Scripting.Ast;
#else
using System.Linq.Expressions;
#endif
#if SILVERLIGHT
using System.Core;
#endif
using System.Collections.Generic;
namespace System.Dynamic.Utils {
// Like ReadOnlyCollection<T>: wraps an IDictionary<K, V> in a read-only wrapper
internal sealed class ReadOnlyDictionary<K, V> : IDictionary<K, V> {
// For wrapping non-readonly Keys, Values collections
// Not used for standard dictionaries, which return read-only Keys and Values
private sealed class ReadOnlyWrapper<T> : ICollection<T> {
// no idea why this warning is here
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
private readonly ICollection<T> _collection;
internal ReadOnlyWrapper(ICollection<T> collection) {
_collection = collection;
}
#region ICollection<T> Members
public void Add(T item) {
throw Error.CollectionReadOnly();
}
public void Clear() {
throw Error.CollectionReadOnly();
}
public bool Contains(T item) {
return _collection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
_collection.CopyTo(array, arrayIndex);
}
public int Count {
get { return _collection.Count; }
}
public bool IsReadOnly {
get { return true; }
}
public bool Remove(T item) {
throw Error.CollectionReadOnly();
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator() {
return _collection.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _collection.GetEnumerator();
}
#endregion
}
private readonly IDictionary<K, V> _dict;
internal ReadOnlyDictionary(IDictionary<K, V> dict) {
ReadOnlyDictionary<K, V> rodict = dict as ReadOnlyDictionary<K, V>;
_dict = (rodict != null) ? rodict._dict : dict;
}
#region IDictionary<K,V> Members
public bool ContainsKey(K key) {
return _dict.ContainsKey(key);
}
public ICollection<K> Keys {
get {
ICollection<K> keys = _dict.Keys;
if (!keys.IsReadOnly) {
return new ReadOnlyWrapper<K>(keys);
}
return keys;
}
}
public bool TryGetValue(K key, out V value) {
return _dict.TryGetValue(key, out value);
}
public ICollection<V> Values {
get {
ICollection<V> values = _dict.Values;
if (!values.IsReadOnly) {
return new ReadOnlyWrapper<V>(values);
}
return values;
}
}
public V this[K key] {
get {
return _dict[key];
}
}
void IDictionary<K, V>.Add(K key, V value) {
throw Error.CollectionReadOnly();
}
bool IDictionary<K, V>.Remove(K key) {
throw Error.CollectionReadOnly();
}
V IDictionary<K, V>.this[K key] {
get {
return _dict[key];
}
set {
throw Error.CollectionReadOnly();
}
}
#endregion
#region ICollection<KeyValuePair<K,V>> Members
public bool Contains(KeyValuePair<K, V> item) {
return _dict.Contains(item);
}
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) {
_dict.CopyTo(array, arrayIndex);
}
public int Count {
get { return _dict.Count; }
}
public bool IsReadOnly {
get { return true; }
}
void ICollection<KeyValuePair<K, V>>.Add(KeyValuePair<K, V> item) {
throw Error.CollectionReadOnly();
}
void ICollection<KeyValuePair<K, V>>.Clear() {
throw Error.CollectionReadOnly();
}
bool ICollection<KeyValuePair<K,V>>.Remove(KeyValuePair<K, V> item) {
throw Error.CollectionReadOnly();
}
#endregion
#region IEnumerable<KeyValuePair<K,V>> Members
public IEnumerator<KeyValuePair<K, V>> GetEnumerator() {
return _dict.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _dict.GetEnumerator();
}
#endregion
}
}

View File

@@ -0,0 +1,34 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Dynamic.Utils {
internal sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> {
internal static readonly ReferenceEqualityComparer<T> Instance = new ReferenceEqualityComparer<T>();
private ReferenceEqualityComparer() { }
public bool Equals(T x, T y) {
return object.ReferenceEquals(x, y);
}
public int GetHashCode(T obj) {
// CF RH.GetHashCode throws NullReferenceException if the argument is null
return obj != null ? RuntimeHelpers.GetHashCode(obj) : 0;
}
}
}

View File

@@ -0,0 +1,7 @@
using System;
namespace Microsoft.Scripting.Utils {
internal static class ReflectionUtils {
public static readonly Type[] EmptyTypes = new Type[0];
}
}

View File

@@ -0,0 +1,63 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
namespace System.Runtime.CompilerServices {
/// <summary>
/// Holds a reference to a value.
/// </summary>
/// <typeparam name="T">The type of the value that the <see cref = "StrongBox{T}"></see> references.</typeparam>
public class StrongBox<T> : IStrongBox {
/// <summary>
/// Gets the strongly typed value associated with the <see cref = "StrongBox{T}"></see>
/// <remarks>This is explicitly exposed as a field instead of a property to enable loading the address of the field.</remarks>
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
public T Value;
/// <summary>
/// Initializes a new StrongBox which can receive a value when used in a reference call.
/// </summary>
public StrongBox() {
}
/// <summary>
/// Initializes a new <see cref = "StrongBox{T}"></see> with the specified value.
/// </summary>
/// <param name="value">A value that the <see cref = "StrongBox{T}"></see> will reference.</param>
public StrongBox(T value) {
Value = value;
}
object IStrongBox.Value {
get {
return Value;
}
set {
Value = (T)value;
}
}
}
/// <summary>
/// Defines a property for accessing the value that an object references.
/// </summary>
public interface IStrongBox {
/// <summary>
/// Gets or sets the value the object references.
/// </summary>
object Value { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic.Utils;
namespace System.Runtime.CompilerServices {
sealed class TrueReadOnlyCollection<T> : ReadOnlyCollection<T> {
/// <summary>
/// Creates instnace of TrueReadOnlyCollection, wrapping passed in array.
/// !!! DOES NOT COPY THE ARRAY !!!
/// </summary>
internal TrueReadOnlyCollection(T[] list)
: base(list) {
}
}
}

View File

@@ -0,0 +1,114 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Diagnostics;
using System.Reflection;
#if FEATURE_REFEMIT
using System.Reflection.Emit;
#endif
using System.Text;
namespace System.Dynamic.Utils {
// Extensions on System.Type and friends
internal static class TypeExtensions {
/// <summary>
/// Creates a closed delegate for the given (dynamic)method.
/// </summary>
internal static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
Debug.Assert(methodInfo != null && delegateType != null);
#if FEATURE_REFEMIT
var dm = methodInfo as DynamicMethod;
if (dm != null)
return dm.CreateDelegate(delegateType, target);
#endif
return Delegate.CreateDelegate(delegateType, target, methodInfo);
}
internal static Type GetReturnType(this MethodBase mi) {
return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
}
private static readonly CacheDict<MethodBase, ParameterInfo[]> _ParamInfoCache = new CacheDict<MethodBase, ParameterInfo[]>(75);
internal static ParameterInfo[] GetParametersCached(this MethodBase method) {
ParameterInfo[] pis;
lock (_ParamInfoCache) {
if (!_ParamInfoCache.TryGetValue(method, out pis)) {
pis = method.GetParameters();
Type t = method.DeclaringType;
if (t != null && TypeUtils.CanCache(t)) {
_ParamInfoCache[method] = pis;
}
}
}
return pis;
}
// Expression trees/compiler just use IsByRef, why do we need this?
// (see LambdaCompiler.EmitArguments for usage in the compiler)
internal static bool IsByRefParameter(this ParameterInfo pi) {
// not using IsIn/IsOut properties as they are not available in Silverlight:
if (pi.ParameterType.IsByRef) return true;
return (pi.Attributes & (ParameterAttributes.Out)) == ParameterAttributes.Out;
}
// Returns the matching method if the parameter types are reference
// assignable from the provided type arguments, otherwise null.
internal static MethodInfo GetMethodValidated(
this Type type,
string name,
BindingFlags bindingAttr,
Binder binder,
Type[] types,
ParameterModifier[] modifiers) {
var method = type.GetMethod(name, bindingAttr, binder, types, modifiers);
return method.MatchesArgumentTypes(types) ? method : null;
}
/// <summary>
/// Returns true if the method's parameter types are reference assignable from
/// the argument types, otherwise false.
///
/// An example that can make the method return false is that
/// typeof(double).GetMethod("op_Equality", ..., new[] { typeof(double), typeof(int) })
/// returns a method with two double parameters, which doesn't match the provided
/// argument types.
/// </summary>
/// <returns></returns>
private static bool MatchesArgumentTypes(this MethodInfo mi, Type[] argTypes) {
if (mi == null || argTypes == null) {
return false;
}
var ps = mi.GetParameters();
if (ps.Length != argTypes.Length) {
return false;
}
for (int i = 0; i < ps.Length; i++) {
if (!TypeUtils.AreReferenceAssignable(ps[i].ParameterType, argTypes[i])) {
return false;
}
}
return true;
}
}
}