Created
July 16, 2011 09:54
-
-
Save takeshik/1086218 to your computer and use it in GitHub Desktop.
.NET Reflector vs. ILSpy vs. dotPeek
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Original | |
public static Expression DispatchMethod( | |
Expression instance, | |
IEnumerable<MethodBase> methods, | |
IList<Type> typeArguments, | |
IList<Expression> arguments | |
) | |
{ | |
return methods | |
.Select(m => m is MethodInfo && ((MethodInfo) m).IsExtensionMethod() | |
? new Candidate(null, m, null, arguments.StartWith(instance).ToArray()) | |
: new Candidate(instance, m, null, arguments) | |
) | |
.If(_ => typeArguments != null && typeArguments.Any(), s => s | |
.Where(_ => _.MethodBase != null && _.MethodBase.IsGenericMethodDefinition && _.MethodBase.GetGenericArguments().Length == typeArguments.Count) | |
.Select(_ => _.Method.MakeGenericMethod(typeArguments.ToArray()) | |
.Let(m => new Candidate(_.Instance, m, m.GetGenericParameterMap(), arguments)) | |
) | |
) | |
.Where(t => t.Instance != null ^ (t.MethodBase.IsStatic || t.Constructor != null) | |
&& t.MethodBase.GetParameters().If(_ => t.MethodBase.IsParamArrayMethod(), | |
ps => t.Arguments.Count >= ps.Length - 1 | |
&& ps.SkipLast(1).Zip(t.Arguments, | |
(p, a) => IsAppropriate(p.ParameterType, a.Type) | |
).All(_ => _) | |
&& EnumerableEx.Repeat(ps.Last()).Zip(t.Arguments.Skip(ps.Length - 1), | |
(p, a) => IsAppropriate(p.ParameterType.GetElementType(), a.Type) | |
).All(_ => _), | |
ps => t.Arguments.Count == ps.Length | |
&& ps.Zip(t.Arguments, | |
(p, a) => IsAppropriate(p.ParameterType, a.Type) | |
).All(_ => _) | |
) | |
) | |
.Select(t => t | |
.If(_ => _.MethodBase != null && _.MethodBase.IsGenericMethod, _ => | |
InferTypeArguments(t.MethodBase.GetParameters().Select(p => p.ParameterType), t.Arguments.Select(e => e.Type)) | |
.Let(m => new Candidate(_.Instance, _.Method.MakeGenericMethod(m.Values.ToArray()), m, _.Arguments)) | |
) | |
.If(_ => _.MethodBase.IsParamArrayMethod(), _ => | |
_.MethodBase.GetParameters().Let(ps => | |
ps.Last().ParameterType.GetElementType().Let(et => | |
new Candidate(_.Instance, _.MethodBase, _.TypeArgumentMap, _.Arguments | |
.Take(ps.Length - 1) | |
.Concat(EnumerableEx.Return(Expression.NewArrayInit(et, _.Arguments | |
.Skip(ps.Length - 1) | |
.Select(e => e.TryConvert(et)) | |
))) | |
.ToArray() | |
) | |
) | |
) | |
) | |
) | |
.OrderBy(t => t.MethodBase.IsParamArrayMethod()) | |
.ThenBy(t => t.Method != null && t.Method.IsExtensionMethod()) | |
.ThenByDescending(t => t.TypeArgumentMap.Count) | |
.FirstOrDefault() | |
.Null(_ => _.If( | |
t => t.Method != null, | |
t => t.Instance != null | |
? (Expression) Expression.Call(t.Instance, t.Method, t.Arguments) | |
: Expression.Call(t.Method, t.Arguments), | |
t => Expression.New(t.Constructor, t.Arguments) | |
)); | |
} | |
// .NET Reflector 7.3.0.18 | |
public static Expression DispatchMethod(Expression instance, IEnumerable<MethodBase> methods, IList<Type> typeArguments, IList<Expression> arguments) | |
{ | |
return (from t in (from m in methods select ((m is MethodInfo) && ((MethodInfo) m).IsExtensionMethod()) ? ((IEnumerable<Candidate>) ((Func<MethodBase, Candidate>) new Candidate(null, m, null, arguments.StartWith<Expression>(instance).ToArray<Expression>()))) : ((IEnumerable<Candidate>) ((Func<MethodBase, Candidate>) new Candidate(instance, m, null, arguments)))).If<IEnumerable<Candidate>>(_ => (typeArguments != null) && typeArguments.Any<Type>(), (Func<IEnumerable<Candidate>, IEnumerable<Candidate>>) (s => (from _ in s | |
where ((_.MethodBase != null) && _.MethodBase.IsGenericMethodDefinition) && (_.MethodBase.GetGenericArguments().Length == typeArguments.Count) | |
select _.Method.MakeGenericMethod(typeArguments.ToArray<Type>()).Let<MethodInfo, Candidate>(m => new Candidate(_.Instance, m, m.GetGenericParameterMap(), arguments))))) | |
where !((t.Instance != null) ^ (t.MethodBase.IsStatic || (t.Constructor != null))) ? ((IEnumerable<Candidate>) ((Func<Candidate, bool>) false)) : ((IEnumerable<Candidate>) ((Func<Candidate, bool>) t.MethodBase.GetParameters().If<ParameterInfo[], bool>(_ => t.MethodBase.IsParamArrayMethod(), ps => (((t.Arguments.Count >= (ps.Length - 1)) && ps.SkipLast<ParameterInfo>(1).Zip<ParameterInfo, Expression, bool>(t.Arguments, (p, a) => IsAppropriate(p.ParameterType, a.Type)).All<bool>(_ => _)) && EnumerableEx.Repeat<ParameterInfo>(ps.Last<ParameterInfo>()).Zip<ParameterInfo, Expression, bool>(t.Arguments.Skip<Expression>((ps.Length - 1)), (p, a) => IsAppropriate(p.ParameterType.GetElementType(), a.Type)).All<bool>(_ => _)), ps => ((t.Arguments.Count == ps.Length) && ps.Zip<ParameterInfo, Expression, bool>(t.Arguments, (p, a) => IsAppropriate(p.ParameterType, a.Type)).All<bool>(_ => _))))) | |
select t.If<Candidate>(_ => ((_.MethodBase != null) && _.MethodBase.IsGenericMethod), ((Func<Candidate, Candidate>) (_ => InferTypeArguments(from p in t.MethodBase.GetParameters() select p.ParameterType, from e in t.Arguments select e.Type).Let<Dictionary<Type, Type>, Candidate>(m => new Candidate(_.Instance, _.Method.MakeGenericMethod(m.Values.ToArray<Type>()), m, _.Arguments))))).If<Candidate>(_ => _.MethodBase.IsParamArrayMethod(), (Func<Candidate, Candidate>) (_ => _.MethodBase.GetParameters().Let<ParameterInfo[], Candidate>(ps => ps.Last<ParameterInfo>().ParameterType.GetElementType().Let<Type, Candidate>(et => new Candidate(_.Instance, _.MethodBase, _.TypeArgumentMap, _.Arguments.Take<Expression>((ps.Length - 1)).Concat<Expression>(EnumerableEx.Return<NewArrayExpression>(Expression.NewArrayInit(et, (IEnumerable<Expression>) (from e in _.Arguments.Skip<Expression>(ps.Length - 1) select e.TryConvert(et))))).ToArray<Expression>()))))) into t | |
orderby t.MethodBase.IsParamArrayMethod(), (t.Method != null) && t.Method.IsExtensionMethod(), t.TypeArgumentMap.Count descending | |
select t).FirstOrDefault<Candidate>().Null<Candidate, Expression>(_ => _.If<Candidate, Expression>(t => (t.Method != null), t => ((t.Instance != null) ? ((Func<Candidate, Expression>) Expression.Call(t.Instance, t.Method, t.Arguments)) : ((Func<Candidate, Expression>) Expression.Call(t.Method, t.Arguments))), t => Expression.New(t.Constructor, t.Arguments))); | |
} | |
// ILSpy version 1.0.0.1000 | |
public static Expression DispatchMethod(Expression instance, IEnumerable<MethodBase> methods, IList<Type> typeArguments, IList<Expression> arguments) | |
{ | |
return ( | |
from t in ( | |
from m in methods | |
select (m is MethodInfo && ((MethodInfo)m).IsExtensionMethod()) ? new Dispatcher.Candidate(null, m, null, arguments.StartWith(instance).ToArray<Expression>()) : new Dispatcher.Candidate(instance, m, null, arguments)).If((IEnumerable<Dispatcher.Candidate> _) => typeArguments != null && typeArguments.Any<Type>(), (IEnumerable<Dispatcher.Candidate> s) => | |
from _ in s | |
where _.MethodBase != null && _.MethodBase.IsGenericMethodDefinition && _.MethodBase.GetGenericArguments().Length == typeArguments.Count | |
select _.Method.MakeGenericMethod(typeArguments.ToArray<Type>()).Let((MethodInfo m) => new Dispatcher.Candidate(_.Instance, m, m.GetGenericParameterMap(), arguments))) | |
where (t.Instance != null ^ (t.MethodBase.IsStatic || t.Constructor != null)) && t.MethodBase.GetParameters().If((ParameterInfo[] _) => t.MethodBase.IsParamArrayMethod(), delegate(ParameterInfo[] ps) | |
{ | |
int arg_E1_0; | |
if (t.Arguments.Count >= ps.Length - 1) | |
{ | |
if (ps.SkipLast(1).Zip(t.Arguments, (ParameterInfo p, Expression a) => Dispatcher.IsAppropriate(p.ParameterType, a.Type)).All((bool _) => _)) | |
{ | |
arg_E1_0 = (EnumerableEx.Repeat<ParameterInfo>(ps.Last<ParameterInfo>()).Zip(t.Arguments.Skip(ps.Length - 1), (ParameterInfo p, Expression a) => Dispatcher.IsAppropriate(p.ParameterType.GetElementType(), a.Type)).All((bool _) => _) ? 1 : 0); | |
return arg_E1_0 != 0; | |
} | |
} | |
arg_E1_0 = 0; | |
return arg_E1_0 != 0; | |
} | |
, delegate(ParameterInfo[] ps) | |
{ | |
bool arg_6C_0; | |
if (t.Arguments.Count == ps.Length) | |
{ | |
arg_6C_0 = ps.Zip(t.Arguments, (ParameterInfo p, Expression a) => Dispatcher.IsAppropriate(p.ParameterType, a.Type)).All((bool _) => _); | |
} | |
else | |
{ | |
arg_6C_0 = false; | |
} | |
return arg_6C_0; | |
} | |
) | |
select t.If((Dispatcher.Candidate _) => _.MethodBase != null && _.MethodBase.IsGenericMethod, (Dispatcher.Candidate _) => Dispatcher.InferTypeArguments( | |
from p in t.MethodBase.GetParameters() | |
select p.ParameterType, t.Arguments.Select((Expression e) => e.Type)).Let((Dictionary<Type, Type> m) => new Dispatcher.Candidate(_.Instance, _.Method.MakeGenericMethod(m.Values.ToArray<Type>()), m, _.Arguments))).If((Dispatcher.Candidate _) => _.MethodBase.IsParamArrayMethod(), (Dispatcher.Candidate _) => _.MethodBase.GetParameters().Let((ParameterInfo[] ps) => ps.Last<ParameterInfo>().ParameterType.GetElementType().Let((Type et) => new Dispatcher.Candidate(_.Instance, _.MethodBase, _.TypeArgumentMap, _.Arguments.Take(ps.Length - 1).Concat(EnumerableEx.Return<NewArrayExpression>(Expression.NewArrayInit(et, | |
from e in _.Arguments.Skip(ps.Length - 1) | |
select e.TryConvert(et)))).ToArray<Expression>())))) into t | |
orderby t.MethodBase.IsParamArrayMethod(), t.Method != null && t.Method.IsExtensionMethod(), t.TypeArgumentMap.Count descending | |
select t).FirstOrDefault<Dispatcher.Candidate>().Null((Dispatcher.Candidate _) => _.If((Dispatcher.Candidate t) => t.Method != null, (Dispatcher.Candidate t) => (t.Instance != null) ? Expression.Call(t.Instance, t.Method, t.Arguments) : Expression.Call(t.Method, t.Arguments), (Dispatcher.Candidate t) => Expression.New(t.Constructor, t.Arguments))); | |
} | |
// dotPeek 1.0.0.2545 | |
public static Expression DispatchMethod(Expression instance, IEnumerable<MethodBase> methods, IList<Type> typeArguments, IList<Expression> arguments) | |
{ | |
return Extension.Null<Dispatcher.Candidate, Expression>(Enumerable.FirstOrDefault<Dispatcher.Candidate>((IEnumerable<Dispatcher.Candidate>) Enumerable.ThenByDescending<Dispatcher.Candidate, int>(Enumerable.ThenBy<Dispatcher.Candidate, bool>(Enumerable.OrderBy<Dispatcher.Candidate, bool>(Enumerable.Select<Dispatcher.Candidate, Dispatcher.Candidate>(Enumerable.Where<Dispatcher.Candidate>(Extension.If<IEnumerable<Dispatcher.Candidate>>(Enumerable.Select<MethodBase, Dispatcher.Candidate>(methods, (Func<MethodBase, Dispatcher.Candidate>) (m => !(m is MethodInfo) || !Dispatcher.IsExtensionMethod((MethodInfo) m) ? new Dispatcher.Candidate(instance, (MemberInfo) m, (IDictionary<Type, Type>) null, arguments) : new Dispatcher.Candidate((Expression) null, (MemberInfo) m, (IDictionary<Type, Type>) null, (IList<Expression>) Enumerable.ToArray<Expression>(EnumerableEx.StartWith<Expression>((IEnumerable<Expression>) arguments, instance))))), (Func<IEnumerable<Dispatcher.Candidate>, bool>) (_ => typeArguments != null && Enumerable.Any<Type>((IEnumerable<Type>) typeArguments)), (Func<IEnumerable<Dispatcher.Candidate>, IEnumerable<Dispatcher.Candidate>>) (s => Enumerable.Select<Dispatcher.Candidate, Dispatcher.Candidate>(Enumerable.Where<Dispatcher.Candidate>(s, (Func<Dispatcher.Candidate, bool>) (_ => _.MethodBase != (MethodBase) null && _.MethodBase.IsGenericMethodDefinition && _.MethodBase.GetGenericArguments().Length == typeArguments.Count)), (Func<Dispatcher.Candidate, Dispatcher.Candidate>) (_ => Extension.Let<MethodInfo, Dispatcher.Candidate>(_.Method.MakeGenericMethod(Enumerable.ToArray<Type>((IEnumerable<Type>) typeArguments)), (Func<MethodInfo, Dispatcher.Candidate>) (m => new Dispatcher.Candidate(_.Instance, (MemberInfo) m, (IDictionary<Type, Type>) Dispatcher.GetGenericParameterMap(m), arguments))))))), (Func<Dispatcher.Candidate, bool>) (t => ((t.Instance != null ? 1 : 0) ^ (t.MethodBase.IsStatic ? 1 : (t.Constructor != (ConstructorInfo) null ? 1 : 0))) != 0 && Extension.If<ParameterInfo[], bool>(t.MethodBase.GetParameters(), (Func<ParameterInfo[], bool>) (_ => Dispatcher.IsParamArrayMethod(t.MethodBase)), (Func<ParameterInfo[], bool>) (ps => t.Arguments.Count >= ps.Length - 1 && Enumerable.All<bool>(Enumerable.Zip<ParameterInfo, Expression, bool>(EnumerableEx.SkipLast<ParameterInfo>((IEnumerable<ParameterInfo>) ps, 1), (IEnumerable<Expression>) t.Arguments, (Func<ParameterInfo, Expression, bool>) ((p, a) => Dispatcher.IsAppropriate(p.ParameterType, a.Type))), (Func<bool, bool>) (_ => _)) && Enumerable.All<bool>(Enumerable.Zip<ParameterInfo, Expression, bool>(EnumerableEx.Repeat<ParameterInfo>(Enumerable.Last<ParameterInfo>((IEnumerable<ParameterInfo>) ps)), Enumerable.Skip<Expression>((IEnumerable<Expression>) t.Arguments, ps.Length - 1), (Func<ParameterInfo, Expression, bool>) ((p, a) => Dispatcher.IsAppropriate(p.ParameterType.GetElementType(), a.Type))), (Func<bool, bool>) (_ => _))), (Func<ParameterInfo[], bool>) (ps => t.Arguments.Count == ps.Length && Enumerable.All<bool>(Enumerable.Zip<ParameterInfo, Expression, bool>((IEnumerable<ParameterInfo>) ps, (IEnumerable<Expression>) t.Arguments, (Func<ParameterInfo, Expression, bool>) ((p, a) => Dispatcher.IsAppropriate(p.ParameterType, a.Type))), (Func<bool, bool>) (_ => _)))))), (Func<Dispatcher.Candidate, Dispatcher.Candidate>) (t => Extension.If<Dispatcher.Candidate>(Extension.If<Dispatcher.Candidate>(t, (Func<Dispatcher.Candidate, bool>) (_ => _.MethodBase != (MethodBase) null && _.MethodBase.IsGenericMethod), (Func<Dispatcher.Candidate, Dispatcher.Candidate>) (_ => Extension.Let<Dictionary<Type, Type>, Dispatcher.Candidate>(Dispatcher.InferTypeArguments(Enumerable.Select<ParameterInfo, Type>((IEnumerable<ParameterInfo>) t.MethodBase.GetParameters(), (Func<ParameterInfo, Type>) (p => p.ParameterType)), Enumerable.Select<Expression, Type>((IEnumerable<Expression>) t.Arguments, (Func<Expression, Type>) (e => e.Type))), (Func<Dictionary<Type, Type>, Dispatcher.Candidate>) (m => new Dispatcher.Candidate(_.Instance, (MemberInfo) _.Method.MakeGenericMethod(Enumerable.ToArray<Type>((IEnumerable<Type>) m.Values)), (IDictionary<Type, Type>) m, _.Arguments))))), (Func<Dispatcher.Candidate, bool>) (_ => Dispatcher.IsParamArrayMethod(_.MethodBase)), (Func<Dispatcher.Candidate, Dispatcher.Candidate>) (_ => Extension.Let<ParameterInfo[], Dispatcher.Candidate>(_.MethodBase.GetParameters(), (Func<ParameterInfo[], Dispatcher.Candidate>) (ps => Extension.Let<Type, Dispatcher.Candidate>(Enumerable.Last<ParameterInfo>((IEnumerable<ParameterInfo>) ps).ParameterType.GetElementType(), (Func<Type, Dispatcher.Candidate>) (et => new Dispatcher.Candidate(_.Instance, (MemberInfo) _.MethodBase, _.TypeArgumentMap, (IList<Expression>) Enumerable.ToArray<Expression>(Enumerable.Concat<Expression>(Enumerable.Take<Expression>((IEnumerable<Expression>) _.Arguments, ps.Length - 1), (IEnumerable<Expression>) EnumerableEx.Return<NewArrayExpression>(Expression.NewArrayInit(et, Enumerable.Select<Expression, Expression>(Enumerable.Skip<Expression>((IEnumerable<Expression>) _.Arguments, ps.Length - 1), (Func<Expression, Expression>) (e => Extension.TryConvert(e, et)))))))))))))))), (Func<Dispatcher.Candidate, bool>) (t => Dispatcher.IsParamArrayMethod(t.MethodBase))), (Func<Dispatcher.Candidate, bool>) (t => t.Method != (MethodInfo) null && Dispatcher.IsExtensionMethod(t.Method))), (Func<Dispatcher.Candidate, int>) (t => t.TypeArgumentMap.Count))), (Func<Dispatcher.Candidate, Expression>) (_ => Extension.If<Dispatcher.Candidate, Expression>(_, (Func<Dispatcher.Candidate, bool>) (t => t.Method != (MethodInfo) null), (Func<Dispatcher.Candidate, Expression>) (t => t.Instance != null ? (Expression) Expression.Call(t.Instance, t.Method, (IEnumerable<Expression>) t.Arguments) : (Expression) Expression.Call(t.Method, (IEnumerable<Expression>) t.Arguments)), (Func<Dispatcher.Candidate, Expression>) (t => (Expression) Expression.New(t.Constructor, (IEnumerable<Expression>) t.Arguments))))); | |
} |
takeshik, I think it's a really cool project you're working on -- I've got nothing as nifty to share with the world :)
By the way, thank you for posting this gist. I'm amazed at the power of a FOSS tool like ILSpy compared to Reflector and dotPeek.
Any way you could also run this battle through dnSpy? https://github.com/0xd4d/dnSpy. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey, jarz. Thanks for reading my (garbage) code :)
This code fragment is to select method / member from candidates, part of my embedded language
(https://github.com/takeshik/yacq , see Dispatcher.cs & Extension.cs ; note below code is removed and was rewritten),
and all methods you don't know is private extension methods.
In decompiling, they are only method calls, so I thought this (using non-standard extension methods) is not big issue.
This is only serious joke, so please don't take seriously!