Skip to content

Instantly share code, notes, and snippets.

@takeshik
Created July 16, 2011 09:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takeshik/1086218 to your computer and use it in GitHub Desktop.
Save takeshik/1086218 to your computer and use it in GitHub Desktop.
.NET Reflector vs. ILSpy vs. dotPeek
// 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
Copy link
Author

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!

@jarz
Copy link

jarz commented Aug 2, 2011

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.

@CodeCharm
Copy link

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