CallSite <> p__site при декомпиляции большой базы кода - PullRequest
0 голосов
/ 30 мая 2019

У меня большая база кода от клиента, разработчик которого отказался предоставить код.

Я декомпилировал основную его часть, хотя у меня возникли проблемы с выполнением

Я использую dnSpy, Just Decompile, dotPeek для декомпиляции кода.Я пытался гуглить и просмотрел Stackoverflow, но не смог найти ничего, что могло бы мне ответить.Я был бы очень признателен, если бы кто-то указал мне правильное направление.

Обновление: Я вставил полную функцию

public virtual string ParseDealerInventoryLink(string toParseLinkData)
        {
            string pattern = "{([^}]+)}";
            string text = toParseLinkData;
            RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
            if (this != null && !string.IsNullOrWhiteSpace(text))
            {
                object dyn = new PropertyBag(this);
                Regex regex = new Regex(pattern, options);
                Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = DealerInventoryFeedUrlParser.GetLinkPatternParamValueMap();
                text = regex.Replace(text, delegate(Match mat)
                {
                    if (mat.Success && mat.Groups.Count > 0)
                    {
                        Group group = mat.Groups[mat.Groups.Count - 1];
                        if (group.Success)
                        {
                            string value = group.Value;
                            if (linkPatternMap.ContainsKey(value))
                            {
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
                                }
                                Func<CallSite, object, string> target = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1.Target;
                                CallSite <>p__Site = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1;
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, Type, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(CSharpBinderFlags.None, "ToString", null, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[]
                                    {
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                                    }));
                                }
                                Func<CallSite, Type, object, object> target2 = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2.Target;
                                CallSite <>p__Site2 = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2;
                                Type typeFromHandle = typeof(Convert);
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3 = CallSite<Func<CallSite, object, string, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetIndex(CSharpBinderFlags.None, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[]
                                    {
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                                    }));
                                }
                                return target(<>p__Site, target2(<>p__Site2, typeFromHandle, DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3.Target(DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3, dyn, linkPatternMap[value].ColumnName)));
                            }
                        }
                    }
                    return mat.Value;
                });
            }
            return text;
        }

1 Ответ

0 голосов
/ 30 мая 2019
class DealerInventoryFeedUrlParser
{
    void ParseDealerInventoryLink()
    {
        dynamic input = new object();
        string link = input;
    }
}

генерирует следующее при компиляции и затем декомпиляции в ILSpy:

class DealerInventoryFeedUrlParser
{
    private void ParseDealerInventoryLink()
    {
        object input = new object();
        if (<>o__0.<>p__0 == null)
        {
            <>o__0.<>p__0 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
        }
        string link = <>o__0.<>p__0.Target(<>o__0.<>p__0, input);
    }
  }

... которое я бы классифицировал как "достаточно близкое".

Нет особой причиныЯ выбрал new object() в качестве значения, присвоенного dynamic.Это могло быть int, string - что угодно.Код инициализации CallSite будет выглядеть так же.T2 в CallSite<Func<T1, T2, TResult>> является всегда объектом, поэтому вы не будете знать, каково ваше реальное входное значение, если вы не посмотрите на местоположение в декомпилированном источнике, где фактически используется DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1.

РЕДАКТИРОВАТЬ

Теперь, когда полный исходный код был опубликован, давайте попробуем собрать кусочки вместе:

class DealerInventoryFeedUrlParser
{
    static Dictionary<string, DealerInventoryLinkPatternParam> GetLinkPatternParamValueMap() => throw new NotImplementedException();

    public virtual string ParseDealerInventoryLink(string toParseLinkData)
    {
        string pattern = "{([^}]+)}";
        string text = toParseLinkData;
        RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
        if (/*this != null &&*/ !string.IsNullOrWhiteSpace(text))
        {
            dynamic dyn = new PropertyBag(this);
            Regex regex = new Regex(pattern, options);
            Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = GetLinkPatternParamValueMap();
            text = regex.Replace(text, delegate (Match mat)
            {
                if (mat.Success && mat.Groups.Count > 0)
                {
                    Group group = mat.Groups[mat.Groups.Count - 1];
                    if (group.Success)
                    {
                        string value = group.Value;
                        if (linkPatternMap.ContainsKey(value))
                        {
                            return Convert.ToString(dyn[linkPatternMap[value].ColumnName]);
                        }
                    }
                }
                return mat.Value;
            });
        }
        return text;
    }
}

class PropertyBag
{
    private readonly object Owner;

    public PropertyBag(object obj)
    {
        Owner = obj;
    }
}

class DealerInventoryLinkPatternParam
{
    public string ColumnName { get; set; }
}

ParseDealerInventoryLink скомпилировано / декомпилировано:

public virtual string ParseDealerInventoryLink(string toParseLinkData)
{
    string pattern = "{([^}]+)}";
    string text = toParseLinkData;
    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
    if (!string.IsNullOrWhiteSpace(text))
    {
        dynamic dyn = new PropertyBag(this);
        Regex regex = new Regex(pattern, options);
        Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = DealerInventoryFeedUrlParser.GetLinkPatternParamValueMap();
        text = regex.Replace(text, delegate(Match mat)
        {
            if (mat.Success && mat.Groups.Count > 0)
            {
                Group group = mat.Groups[mat.Groups.Count - 1];
                if (group.Success)
                {
                    string value = group.Value;
                    if (linkPatternMap.ContainsKey(value))
                    {
                        if (<>o__1.<>p__2 == null)
                        {
                            <>o__1.<>p__2 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
                        }
                        Func<CallSite, object, string> target = <>o__1.<>p__2.Target;
                        CallSite<Func<CallSite, object, string>> <>p__ = <>o__1.<>p__2;
                        if (<>o__1.<>p__1 == null)
                        {
                            <>o__1.<>p__1 = CallSite<Func<CallSite, Type, object, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "ToString", null, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[2]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));
                        }
                        Func<CallSite, Type, object, object> target2 = <>o__1.<>p__1.Target;
                        CallSite<Func<CallSite, Type, object, object>> <>p__2 = <>o__1.<>p__1;
                        Type typeFromHandle = typeof(Convert);
                        if (<>o__1.<>p__0 == null)
                        {
                            <>o__1.<>p__0 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.GetIndex(CSharpBinderFlags.None, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[2]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                            }));
                        }
                        return target(<>p__, target2(<>p__2, typeFromHandle, <>o__1.<>p__0.Target(<>o__1.<>p__0, dyn, linkPatternMap[value].ColumnName)));
                    }
                }
            }
            return mat.Value;
        });
    }
    return text;
}

Вы можете заменить сгенерированные компилятором имена, чтобы проверить, правильно ли я все понял.Я сделал честную, но очень, очень быструю попытку угадать, на что я смотрю, основываясь на моем ограниченном понимании dynamic.Теперь все зависит от вас, чтобы проверить все, проверить правильность и исправить, если необходимо.

PS Бит проверки this != null немного сбил меня с толку.Должно быть причуда декомпилятора.Я прокомментировал это, поскольку это не казалось существенным.

PPS Декомпиляция и перекомпиляция двоичных файлов - довольно грязный и подверженный ошибкам процесс.Если изменения, которые вам нужно внести, невелики, попробуйте изучить бинарное исправление .NET (Google it), т.е. с помощью ILSpy + Reflexil.

Удачи.

...