C# 在运行时解析成员名称
给定一个类型、名称和签名,我如何使用7.4的C#规则(7.4是C#语言规范中的章节号)(或者至少是其中的一部分…假设我可以在运行时使用完全匹配的名称和签名进行成员查找)?我需要获取C# 在运行时解析成员名称,c#,c#-4.0,reflection,c#-5.0,overload-resolution,C#,C# 4.0,Reflection,C# 5.0,Overload Resolution,给定一个类型、名称和签名,我如何使用7.4的C#规则(7.4是C#语言规范中的章节号)(或者至少是其中的一部分…假设我可以在运行时使用完全匹配的名称和签名进行成员查找)?我需要获取MethodInfo/PropertyInfo/。。。因为我必须将它与反射一起使用(更确切地说,我试图构建一个表达式.ForEachbuilder(一个能够创建表示ForEach语句的表达式树的工厂),为了使C#foreach达到像素级完美,我必须能够进行duck键入,并搜索GetEnumerator方法(在集合中)、
MethodInfo
/PropertyInfo
/。。。因为我必须将它与反射一起使用(更确切地说,我试图构建一个表达式.ForEach
builder(一个能够创建表示ForEach
语句的表达式树的工厂),为了使C#foreach
达到像素级完美,我必须能够进行duck键入,并搜索GetEnumerator
方法(在集合中)、Current
属性和MoveNext
方法(在枚举器中),如8.8.4所述
问题(问题的一个例子)
显然,如果我尝试typeof(C3).GetProperty(“Current”)
我会得到一个模糊的MatchException
异常
接口存在类似但不同的问题:
interface I0
{
int Current { get; set; }
}
interface I1 : I0
{
new long Current { get; set; }
}
interface I2 : I1, I0
{
new object Current { get; set; }
}
interface I3 : I2
{
}
在这里,如果我尝试执行typeof(I3).GetProperties()
我不会得到Current
属性(这是已知的,请参见示例),但我不能简单地展平接口,因为这样我就不知道谁隐藏了谁
我知道这个问题可能在Microsoft.CSharp.RuntimeBinder
命名空间(在Microsoft.CSharp
程序集中声明)的某个地方得到了解决。这是因为我试图使用C#规则,当您有动态方法调用时,成员查找是必要的,但我没有找到任何东西(然后我会得到一个表达式,或者直接调用)
经过一番思考后,很明显在Microsoft.VisualBasic
程序集中也有类似的东西。VB.NET支持后期绑定。它位于Microsoft.VisualBasic.CompilerServices.NewLateBinding中,但不公开后期绑定的方法。将重载方法与BindingFlags
参数一起使用
GetProperties(BindingFlags.DeclaredOnly)
(注意:在C#中的方法/属性/事件定义中阴影=隐藏=新建)
没有人响应,所以我会在这段时间内发布我编写的代码。我不想发布400行代码,但我希望完整。主要有两种方法:GetVisibleMethods
和GetVisibleProperties
。它们是类型
类的扩展方法。它们将返回类型的公共可见(非阴影/非重写)方法/属性。他们甚至应该处理VB.NET程序集(VB.NET通常使用按名称隐藏
阴影,而不是像C#那样使用隐藏
)。它们将结果缓存在两个静态集合中(方法
和属性
)。代码是针对C#4.0的,因此我使用的是concurrentdirectionary
。如果您使用的是C#3.5,您可以将其替换为字典
,但在读取和写入时,必须使用锁
(){}对其进行保护
它是如何工作的?它通过递归工作(我知道递归通常是不好的,但我希望没有人会创建一个1.000级的继承链)
对于“实”类型(非接口),它向上走一层(使用递归,因此这一层可以向上走一层,以此类推),并且从返回的方法/属性列表中,它删除了重载/隐藏的方法/属性
对于接口,它稍微复杂一些Type.GetInterfaces()
返回所有继承的接口,忽略它们是直接继承的还是间接继承的。对于这些接口中的每一个,都会计算(通过递归)已声明方法/属性的列表。此列表与接口隐藏的方法/属性列表(HashSet
/HashSet
)配对。由一个或另一个接口隐藏的这些方法/属性将从从接口返回的所有其他方法/属性中删除(因此,如果您使用Method1(int)
,I2
继承了重新声明Method1(int)的I1
)
这样做隐藏了I1.Method1
和I3
继承自I1
和I2
,事实上I2
隐藏了I1.Method1
将应用于探索I1
返回的方法,因此删除I1.Method1(int)
(之所以会发生这种情况,是因为我没有为接口生成继承映射,我只是查看隐藏的内容)
从返回的方法/属性集合中,可以使用Linq查找查找的方法/属性。请注意,使用接口可以找到多个具有给定签名的方法/属性。例如:
interface I1
{
void Method1();
}
interface I2
{
void Method1();
}
interface I3 : I1, I2
{
}
I3
将返回两个Method1()
守则:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class TypeEx
{
/// <summary>
/// Type, Tuple<Methods of type, (for interfaces)methods of base interfaces shadowed>
/// </summary>
public static readonly ConcurrentDictionary<Type, Tuple<MethodInfo[], HashSet<MethodInfo>>> Methods = new ConcurrentDictionary<Type, Tuple<MethodInfo[], HashSet<MethodInfo>>>();
/// <summary>
/// Type, Tuple<Properties of type, (for interfaces)properties of base interfaces shadowed>
/// </summary>
public static readonly ConcurrentDictionary<Type, Tuple<PropertyInfo[], HashSet<PropertyInfo>>> Properties = new ConcurrentDictionary<Type, Tuple<PropertyInfo[], HashSet<PropertyInfo>>>();
public static MethodInfo[] GetVisibleMethods(this Type type)
{
if (type.IsInterface)
{
return (MethodInfo[])type.GetVisibleMethodsInterfaceImpl().Item1.Clone();
}
return (MethodInfo[])type.GetVisibleMethodsImpl().Clone();
}
public static PropertyInfo[] GetVisibleProperties(this Type type)
{
if (type.IsInterface)
{
return (PropertyInfo[])type.GetVisiblePropertiesInterfaceImpl().Item1.Clone();
}
return (PropertyInfo[])type.GetVisiblePropertiesImpl().Clone();
}
private static MethodInfo[] GetVisibleMethodsImpl(this Type type)
{
Tuple<MethodInfo[], HashSet<MethodInfo>> tuple;
if (Methods.TryGetValue(type, out tuple))
{
return tuple.Item1;
}
var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (type.BaseType == null)
{
Methods.TryAdd(type, Tuple.Create(methods, (HashSet<MethodInfo>)null));
return methods;
}
var baseMethods = type.BaseType.GetVisibleMethodsImpl().ToList();
foreach (var method in methods)
{
if (method.IsHideByName())
{
baseMethods.RemoveAll(p => p.Name == method.Name);
}
else
{
int numGenericArguments = method.GetGenericArguments().Length;
var parameters = method.GetParameters();
baseMethods.RemoveAll(p =>
{
if (!method.EqualSignature(numGenericArguments, parameters, p))
{
return false;
}
return true;
});
}
}
if (baseMethods.Count == 0)
{
Methods.TryAdd(type, Tuple.Create(methods, (HashSet<MethodInfo>)null));
return methods;
}
var methods3 = new MethodInfo[methods.Length + baseMethods.Count];
Array.Copy(methods, 0, methods3, 0, methods.Length);
baseMethods.CopyTo(methods3, methods.Length);
Methods.TryAdd(type, Tuple.Create(methods3, (HashSet<MethodInfo>)null));
return methods3;
}
private static Tuple<MethodInfo[], HashSet<MethodInfo>> GetVisibleMethodsInterfaceImpl(this Type type)
{
Tuple<MethodInfo[], HashSet<MethodInfo>> tuple;
if (Methods.TryGetValue(type, out tuple))
{
return tuple;
}
var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
var baseInterfaces = type.GetInterfaces();
if (baseInterfaces.Length == 0)
{
tuple = Tuple.Create(methods, new HashSet<MethodInfo>());
Methods.TryAdd(type, tuple);
return tuple;
}
var baseMethods = new List<MethodInfo>();
var baseMethodsTemp = new MethodInfo[baseInterfaces.Length][];
var shadowedMethods = new HashSet<MethodInfo>();
for (int i = 0; i < baseInterfaces.Length; i++)
{
var tuple2 = baseInterfaces[i].GetVisibleMethodsInterfaceImpl();
baseMethodsTemp[i] = tuple2.Item1;
shadowedMethods.UnionWith(tuple2.Item2);
}
for (int i = 0; i < baseInterfaces.Length; i++)
{
baseMethods.AddRange(baseMethodsTemp[i].Where(p => !shadowedMethods.Contains(p)));
}
foreach (var method in methods)
{
if (method.IsHideByName())
{
baseMethods.RemoveAll(p =>
{
if (p.Name == method.Name)
{
shadowedMethods.Add(p);
return true;
}
return false;
});
}
else
{
int numGenericArguments = method.GetGenericArguments().Length;
var parameters = method.GetParameters();
baseMethods.RemoveAll(p =>
{
if (!method.EqualSignature(numGenericArguments, parameters, p))
{
return false;
}
shadowedMethods.Add(p);
return true;
});
}
}
if (baseMethods.Count == 0)
{
tuple = Tuple.Create(methods, shadowedMethods);
Methods.TryAdd(type, tuple);
return tuple;
}
var methods3 = new MethodInfo[methods.Length + baseMethods.Count];
Array.Copy(methods, 0, methods3, 0, methods.Length);
baseMethods.CopyTo(methods3, methods.Length);
tuple = Tuple.Create(methods3, shadowedMethods);
Methods.TryAdd(type, tuple);
return tuple;
}
private static PropertyInfo[] GetVisiblePropertiesImpl(this Type type)
{
Tuple<PropertyInfo[], HashSet<PropertyInfo>> tuple;
if (Properties.TryGetValue(type, out tuple))
{
return tuple.Item1;
}
var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (type.BaseType == null)
{
Properties.TryAdd(type, Tuple.Create(properties, (HashSet<PropertyInfo>)null));
return properties;
}
var baseProperties = type.BaseType.GetVisiblePropertiesImpl().ToList();
foreach (var property in properties)
{
if (property.IsHideByName())
{
baseProperties.RemoveAll(p => p.Name == property.Name);
}
else
{
var indexers = property.GetIndexParameters();
baseProperties.RemoveAll(p =>
{
if (!property.EqualSignature(indexers, p))
{
return false;
}
return true;
});
}
}
if (baseProperties.Count == 0)
{
Properties.TryAdd(type, Tuple.Create(properties, (HashSet<PropertyInfo>)null));
return properties;
}
var properties3 = new PropertyInfo[properties.Length + baseProperties.Count];
Array.Copy(properties, 0, properties3, 0, properties.Length);
baseProperties.CopyTo(properties3, properties.Length);
Properties.TryAdd(type, Tuple.Create(properties3, (HashSet<PropertyInfo>)null));
return properties3;
}
private static Tuple<PropertyInfo[], HashSet<PropertyInfo>> GetVisiblePropertiesInterfaceImpl(this Type type)
{
Tuple<PropertyInfo[], HashSet<PropertyInfo>> tuple;
if (Properties.TryGetValue(type, out tuple))
{
return tuple;
}
var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
var baseInterfaces = type.GetInterfaces();
if (baseInterfaces.Length == 0)
{
tuple = Tuple.Create(properties, new HashSet<PropertyInfo>());
Properties.TryAdd(type, tuple);
return tuple;
}
var baseProperties = new List<PropertyInfo>();
var basePropertiesTemp = new PropertyInfo[baseInterfaces.Length][];
var shadowedProperties = new HashSet<PropertyInfo>();
for (int i = 0; i < baseInterfaces.Length; i++)
{
var tuple2 = baseInterfaces[i].GetVisiblePropertiesInterfaceImpl();
basePropertiesTemp[i] = tuple2.Item1;
shadowedProperties.UnionWith(tuple2.Item2);
}
for (int i = 0; i < baseInterfaces.Length; i++)
{
baseProperties.AddRange(basePropertiesTemp[i].Where(p => !shadowedProperties.Contains(p)));
}
foreach (var property in properties)
{
if (property.IsHideByName())
{
baseProperties.RemoveAll(p =>
{
if (p.Name == property.Name)
{
shadowedProperties.Add(p);
return true;
}
return false;
});
}
else
{
var indexers = property.GetIndexParameters();
baseProperties.RemoveAll(p =>
{
if (!property.EqualSignature(indexers, p))
{
return false;
}
shadowedProperties.Add(p);
return true;
});
}
}
if (baseProperties.Count == 0)
{
tuple = Tuple.Create(properties, shadowedProperties);
Properties.TryAdd(type, tuple);
return tuple;
}
var properties3 = new PropertyInfo[properties.Length + baseProperties.Count];
Array.Copy(properties, 0, properties3, 0, properties.Length);
baseProperties.CopyTo(properties3, properties.Length);
tuple = Tuple.Create(properties3, shadowedProperties);
Properties.TryAdd(type, tuple);
return tuple;
}
private static bool EqualSignature(this MethodInfo method1, int numGenericArguments1, ParameterInfo[] parameters1, MethodInfo method2)
{
// To shadow by signature a method must have same name, same number of
// generic arguments, same number of parameters and same parameters' type
if (method1.Name != method2.Name)
{
return false;
}
if (numGenericArguments1 != method2.GetGenericArguments().Length)
{
return false;
}
var parameters2 = method2.GetParameters();
if (!parameters1.EqualParameterTypes(parameters2))
{
return false;
}
return true;
}
private static bool EqualSignature(this PropertyInfo property1, ParameterInfo[] indexers1, PropertyInfo property2)
{
// To shadow by signature a property must have same name,
// same number of indexers and same indexers' type
if (property1.Name != property2.Name)
{
return false;
}
var parameters2 = property1.GetIndexParameters();
if (!indexers1.EqualParameterTypes(parameters2))
{
return false;
}
return true;
}
private static bool EqualParameterTypes(this ParameterInfo[] parameters1, ParameterInfo[] parameters2)
{
if (parameters1.Length != parameters2.Length)
{
return false;
}
for (int i = 0; i < parameters1.Length; i++)
{
if (parameters1[i].IsOut != parameters2[i].IsOut)
{
return false;
}
if (parameters1[i].ParameterType.IsGenericParameter)
{
if (!parameters2[i].ParameterType.IsGenericParameter)
{
return false;
}
if (parameters1[i].ParameterType.GenericParameterPosition != parameters2[i].ParameterType.GenericParameterPosition)
{
return false;
}
}
else if (parameters1[i].ParameterType != parameters2[i].ParameterType)
{
return false;
}
}
return true;
}
private static bool IsHideByName(this MethodInfo method)
{
if (!method.Attributes.HasFlag(MethodAttributes.HideBySig) && (!method.Attributes.HasFlag(MethodAttributes.Virtual) || method.Attributes.HasFlag(MethodAttributes.NewSlot)))
{
return true;
}
return false;
}
private static bool IsHideByName(this PropertyInfo property)
{
var get = property.GetGetMethod();
if (get != null && get.IsHideByName())
{
return true;
}
var set = property.GetSetMethod();
if (set != null && set.IsHideByName())
{
return true;
}
return false;
}
}
使用系统;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
公共静态类typex
{
///
///类型,类型的TupleMethods,(对于接口)基本接口的方法隐藏
///
公共静态只读ConcurrentDictionary方法=新建ConcurrentDictionary();
///
///类型,类型的TupleProperty,(对于接口)隐藏的基本接口的属性
///
公共静态只读ConcurrentDictionary属性=新建ConcurrentDictionary();
公共静态MethodInfo[]GetVisibleMethods(此类型)
{
if(类型IsInterface)
{
return(MethodInfo[])type.GetVisibleMethodsInterfaceImpl().Item1.Clone();
}
return(MethodInfo[])type.GetVisibleMethodsImpl().Clone();
}
公共静态属性Info[]GetVisibleProperties(此类型)
{
if(类型IsInterface)
{
雷图
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class TypeEx
{
/// <summary>
/// Type, Tuple<Methods of type, (for interfaces)methods of base interfaces shadowed>
/// </summary>
public static readonly ConcurrentDictionary<Type, Tuple<MethodInfo[], HashSet<MethodInfo>>> Methods = new ConcurrentDictionary<Type, Tuple<MethodInfo[], HashSet<MethodInfo>>>();
/// <summary>
/// Type, Tuple<Properties of type, (for interfaces)properties of base interfaces shadowed>
/// </summary>
public static readonly ConcurrentDictionary<Type, Tuple<PropertyInfo[], HashSet<PropertyInfo>>> Properties = new ConcurrentDictionary<Type, Tuple<PropertyInfo[], HashSet<PropertyInfo>>>();
public static MethodInfo[] GetVisibleMethods(this Type type)
{
if (type.IsInterface)
{
return (MethodInfo[])type.GetVisibleMethodsInterfaceImpl().Item1.Clone();
}
return (MethodInfo[])type.GetVisibleMethodsImpl().Clone();
}
public static PropertyInfo[] GetVisibleProperties(this Type type)
{
if (type.IsInterface)
{
return (PropertyInfo[])type.GetVisiblePropertiesInterfaceImpl().Item1.Clone();
}
return (PropertyInfo[])type.GetVisiblePropertiesImpl().Clone();
}
private static MethodInfo[] GetVisibleMethodsImpl(this Type type)
{
Tuple<MethodInfo[], HashSet<MethodInfo>> tuple;
if (Methods.TryGetValue(type, out tuple))
{
return tuple.Item1;
}
var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (type.BaseType == null)
{
Methods.TryAdd(type, Tuple.Create(methods, (HashSet<MethodInfo>)null));
return methods;
}
var baseMethods = type.BaseType.GetVisibleMethodsImpl().ToList();
foreach (var method in methods)
{
if (method.IsHideByName())
{
baseMethods.RemoveAll(p => p.Name == method.Name);
}
else
{
int numGenericArguments = method.GetGenericArguments().Length;
var parameters = method.GetParameters();
baseMethods.RemoveAll(p =>
{
if (!method.EqualSignature(numGenericArguments, parameters, p))
{
return false;
}
return true;
});
}
}
if (baseMethods.Count == 0)
{
Methods.TryAdd(type, Tuple.Create(methods, (HashSet<MethodInfo>)null));
return methods;
}
var methods3 = new MethodInfo[methods.Length + baseMethods.Count];
Array.Copy(methods, 0, methods3, 0, methods.Length);
baseMethods.CopyTo(methods3, methods.Length);
Methods.TryAdd(type, Tuple.Create(methods3, (HashSet<MethodInfo>)null));
return methods3;
}
private static Tuple<MethodInfo[], HashSet<MethodInfo>> GetVisibleMethodsInterfaceImpl(this Type type)
{
Tuple<MethodInfo[], HashSet<MethodInfo>> tuple;
if (Methods.TryGetValue(type, out tuple))
{
return tuple;
}
var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
var baseInterfaces = type.GetInterfaces();
if (baseInterfaces.Length == 0)
{
tuple = Tuple.Create(methods, new HashSet<MethodInfo>());
Methods.TryAdd(type, tuple);
return tuple;
}
var baseMethods = new List<MethodInfo>();
var baseMethodsTemp = new MethodInfo[baseInterfaces.Length][];
var shadowedMethods = new HashSet<MethodInfo>();
for (int i = 0; i < baseInterfaces.Length; i++)
{
var tuple2 = baseInterfaces[i].GetVisibleMethodsInterfaceImpl();
baseMethodsTemp[i] = tuple2.Item1;
shadowedMethods.UnionWith(tuple2.Item2);
}
for (int i = 0; i < baseInterfaces.Length; i++)
{
baseMethods.AddRange(baseMethodsTemp[i].Where(p => !shadowedMethods.Contains(p)));
}
foreach (var method in methods)
{
if (method.IsHideByName())
{
baseMethods.RemoveAll(p =>
{
if (p.Name == method.Name)
{
shadowedMethods.Add(p);
return true;
}
return false;
});
}
else
{
int numGenericArguments = method.GetGenericArguments().Length;
var parameters = method.GetParameters();
baseMethods.RemoveAll(p =>
{
if (!method.EqualSignature(numGenericArguments, parameters, p))
{
return false;
}
shadowedMethods.Add(p);
return true;
});
}
}
if (baseMethods.Count == 0)
{
tuple = Tuple.Create(methods, shadowedMethods);
Methods.TryAdd(type, tuple);
return tuple;
}
var methods3 = new MethodInfo[methods.Length + baseMethods.Count];
Array.Copy(methods, 0, methods3, 0, methods.Length);
baseMethods.CopyTo(methods3, methods.Length);
tuple = Tuple.Create(methods3, shadowedMethods);
Methods.TryAdd(type, tuple);
return tuple;
}
private static PropertyInfo[] GetVisiblePropertiesImpl(this Type type)
{
Tuple<PropertyInfo[], HashSet<PropertyInfo>> tuple;
if (Properties.TryGetValue(type, out tuple))
{
return tuple.Item1;
}
var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (type.BaseType == null)
{
Properties.TryAdd(type, Tuple.Create(properties, (HashSet<PropertyInfo>)null));
return properties;
}
var baseProperties = type.BaseType.GetVisiblePropertiesImpl().ToList();
foreach (var property in properties)
{
if (property.IsHideByName())
{
baseProperties.RemoveAll(p => p.Name == property.Name);
}
else
{
var indexers = property.GetIndexParameters();
baseProperties.RemoveAll(p =>
{
if (!property.EqualSignature(indexers, p))
{
return false;
}
return true;
});
}
}
if (baseProperties.Count == 0)
{
Properties.TryAdd(type, Tuple.Create(properties, (HashSet<PropertyInfo>)null));
return properties;
}
var properties3 = new PropertyInfo[properties.Length + baseProperties.Count];
Array.Copy(properties, 0, properties3, 0, properties.Length);
baseProperties.CopyTo(properties3, properties.Length);
Properties.TryAdd(type, Tuple.Create(properties3, (HashSet<PropertyInfo>)null));
return properties3;
}
private static Tuple<PropertyInfo[], HashSet<PropertyInfo>> GetVisiblePropertiesInterfaceImpl(this Type type)
{
Tuple<PropertyInfo[], HashSet<PropertyInfo>> tuple;
if (Properties.TryGetValue(type, out tuple))
{
return tuple;
}
var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
var baseInterfaces = type.GetInterfaces();
if (baseInterfaces.Length == 0)
{
tuple = Tuple.Create(properties, new HashSet<PropertyInfo>());
Properties.TryAdd(type, tuple);
return tuple;
}
var baseProperties = new List<PropertyInfo>();
var basePropertiesTemp = new PropertyInfo[baseInterfaces.Length][];
var shadowedProperties = new HashSet<PropertyInfo>();
for (int i = 0; i < baseInterfaces.Length; i++)
{
var tuple2 = baseInterfaces[i].GetVisiblePropertiesInterfaceImpl();
basePropertiesTemp[i] = tuple2.Item1;
shadowedProperties.UnionWith(tuple2.Item2);
}
for (int i = 0; i < baseInterfaces.Length; i++)
{
baseProperties.AddRange(basePropertiesTemp[i].Where(p => !shadowedProperties.Contains(p)));
}
foreach (var property in properties)
{
if (property.IsHideByName())
{
baseProperties.RemoveAll(p =>
{
if (p.Name == property.Name)
{
shadowedProperties.Add(p);
return true;
}
return false;
});
}
else
{
var indexers = property.GetIndexParameters();
baseProperties.RemoveAll(p =>
{
if (!property.EqualSignature(indexers, p))
{
return false;
}
shadowedProperties.Add(p);
return true;
});
}
}
if (baseProperties.Count == 0)
{
tuple = Tuple.Create(properties, shadowedProperties);
Properties.TryAdd(type, tuple);
return tuple;
}
var properties3 = new PropertyInfo[properties.Length + baseProperties.Count];
Array.Copy(properties, 0, properties3, 0, properties.Length);
baseProperties.CopyTo(properties3, properties.Length);
tuple = Tuple.Create(properties3, shadowedProperties);
Properties.TryAdd(type, tuple);
return tuple;
}
private static bool EqualSignature(this MethodInfo method1, int numGenericArguments1, ParameterInfo[] parameters1, MethodInfo method2)
{
// To shadow by signature a method must have same name, same number of
// generic arguments, same number of parameters and same parameters' type
if (method1.Name != method2.Name)
{
return false;
}
if (numGenericArguments1 != method2.GetGenericArguments().Length)
{
return false;
}
var parameters2 = method2.GetParameters();
if (!parameters1.EqualParameterTypes(parameters2))
{
return false;
}
return true;
}
private static bool EqualSignature(this PropertyInfo property1, ParameterInfo[] indexers1, PropertyInfo property2)
{
// To shadow by signature a property must have same name,
// same number of indexers and same indexers' type
if (property1.Name != property2.Name)
{
return false;
}
var parameters2 = property1.GetIndexParameters();
if (!indexers1.EqualParameterTypes(parameters2))
{
return false;
}
return true;
}
private static bool EqualParameterTypes(this ParameterInfo[] parameters1, ParameterInfo[] parameters2)
{
if (parameters1.Length != parameters2.Length)
{
return false;
}
for (int i = 0; i < parameters1.Length; i++)
{
if (parameters1[i].IsOut != parameters2[i].IsOut)
{
return false;
}
if (parameters1[i].ParameterType.IsGenericParameter)
{
if (!parameters2[i].ParameterType.IsGenericParameter)
{
return false;
}
if (parameters1[i].ParameterType.GenericParameterPosition != parameters2[i].ParameterType.GenericParameterPosition)
{
return false;
}
}
else if (parameters1[i].ParameterType != parameters2[i].ParameterType)
{
return false;
}
}
return true;
}
private static bool IsHideByName(this MethodInfo method)
{
if (!method.Attributes.HasFlag(MethodAttributes.HideBySig) && (!method.Attributes.HasFlag(MethodAttributes.Virtual) || method.Attributes.HasFlag(MethodAttributes.NewSlot)))
{
return true;
}
return false;
}
private static bool IsHideByName(this PropertyInfo property)
{
var get = property.GetGetMethod();
if (get != null && get.IsHideByName())
{
return true;
}
var set = property.GetSetMethod();
if (set != null && set.IsHideByName())
{
return true;
}
return false;
}
}