Как я мог использовать поля в методе (.NET)?

Да, возможно определить Ваши собственные учетные данные, не изменяя текущий код. Это требует маленькой части кода от Вашей части все же.

Создают блок, названный SomeAssembly.dll с этим классом:

namespace SomeNameSpace
{
    public class MyProxy : IWebProxy
    {
        public ICredentials Credentials
        {
            get { return new NetworkCredential("user", "password"); }
            //or get { return new NetworkCredential("user", "password","domain"); }
            set { }
        }

        public Uri GetProxy(Uri destination)
        {
            return new Uri("http://my.proxy:8080");
        }

        public bool IsBypassed(Uri host)
        {
            return false;
        }
    }
}

Добавляют это к Вашему файлу конфигурации:


  

Это "вводит" новый прокси в списке, и потому что нет никаких учетных данных по умолчанию, класс WebRequest назовет Ваш код сначала и запросит Ваши собственные учетные данные. Необходимо будет разместить собрать SomeAssembly в каталог bin приложения CMS.

Это - так или иначе статический код, и получить все строки как пользователь, пароль и URL, Вы, возможно, или должны были бы реализовать свое собственное ConfigurationSection или добавить некоторую информацию в AppSettings, который намного более легче.

5
задан kerem 17 September 2009 в 17:54
поделиться

5 ответов

There's a lot of different answers, but as not a single one appeals to me, here's mine. It's using my Reflection based IL reader.

Here's a method retrieving all the fields used by a method:

static IEnumerable<FieldInfo> GetUsedFields (MethodInfo method)
{
    return (from instruction in method.GetInstructions ()
           where instruction.OpCode.OperandType == OperandType.InlineField
           select (FieldInfo) instruction.Operand).Distinct ();
}
10
ответ дан 18 December 2019 в 14:48
поделиться

Вам необходимо получить MethodInfo. Вызовите GetMethodBody (), чтобы получить структуру тела метода, а затем вызовите для этого GetILAsByteArray. Преобразование этого байтового массива в поток понятного IL.

Грубо говоря

public static List<Instruction> ReadIL(MethodInfo method)
{
    MethodBody body = method.GetMethodBody();
    if (body == null)
        return null;

    var instructions = new List<Instruction>();
    int offset = 0;
    byte[] il = body.GetILAsByteArray();
    while (offset < il.Length)
    {
        int startOffset = offset;
        byte opCodeByte = il[offset];
        short opCodeValue = opCodeByte;
        // If it's an extended opcode then grab the second byte. The 0xFE
        // prefix codes aren't marked as prefix operators though. 
        if (OpCodeList[opCodeValue].OpCodeType == OpCodeType.Prefix
            || opCodeValue == 0xFE)
        {
            opCodeValue = (short) ((opCodeValue << 8) + il[offset + 1]);
            offset += 1;
        }
        // Move to the first byte of the argument.
        offset += 1;

        OpCode code = OpCodeList[opCodeValue];

        Int64? argument = null;
        if (code.ArgumentSize() > 0)
        {
            Int64 arg = 0;
            Debug.Assert(code.ArgumentSize() <= 8);
            for (int i = 0; i < code.ArgumentSize(); ++i)
            {
                Int64 v = il[offset + i];
                arg += v << (i*8);
            }
            argument = arg;
            offset += code.ArgumentSize();
        }

        var instruction = new Instruction(startOffset, code, argument);
        instructions.Add(instruction);
    }

    return instructions;
}

, где OpCodeList создается с помощью

OpCodeList = new Dictionary<short, OpCode>();
foreach (var opCode in typeof (OpCodes).GetFields()
                       .Where(f => f.FieldType == typeof (OpCode))
                       .Select(f => (OpCode) f.GetValue(null)))
{
    OpCodeList.Add(opCode.Value, opCode);
}

. Затем вы можете определить, какие инструкции являются вызовами свойств IL или поиском переменных-членов, или что-то еще, что вам нужно, и разрешить их затем с помощью GetType (). Module.ResolveField.

(Код предупреждения выше более или менее работает, но он был взят из более крупного проекта, который я сделал, поэтому, возможно, отсутствуют незначительные детали).

Изменить: Размер аргумента - это метод расширения в OpCode, который просто использует таблицу поиска для выполнения найдите соответствующее значение

public static int ArgumentSize(this OpCode opCode)
{
  Dictionary<OperandType, int> operandSizes 
           = new Dictionary<OperandType, int>()
                 {
                    {OperandType.InlineBrTarget, 4},
                    {OperandType.InlineField, 4},
                    {OperandType.InlineI, 4},
                    // etc., etc.
                 };
  return operandSizes[opCode.OperandType];
}

. Вы найдете размеры в ECMA 335 , которые вы

1
ответ дан 18 December 2019 в 14:48
поделиться

Отражение - это в первую очередь API для проверки метаданных. Что вы пытаетесь сделать, так это проверить необработанный IL, который не является поддерживаемой функцией отражения. Reflection просто возвращает IL в виде необработанного байта [], который необходимо проверить вручную.

-1
ответ дан 18 December 2019 в 14:48
поделиться

@Ian G: Я собрал список из ECMA 335 и обнаружил, что могу использовать

List<MethodInfo> mis = 
    myObject.GetType().GetMethods().Where((MethodInfo mi) =>
        {
            mi.GetCustomAttributes(typeof(MyAttribute), true).Length > 0;
        }
    ).ToList();
foreach(MethodInfo mi in mis)
{
    List<Instruction> lst = ReflectionHelper.ReadIL(mi);
    ... find useful opcode
    FieldInfo fi = mi.Module.ResolveField((int)usefulOpcode.Argument);
    object o = fi.GetValue(myObject);
    ...
}

И список длин опкодов здесь, если кому-то это нужно:

Dictionary<OperandType, int> operandSizes
= new Dictionary<OperandType, int>()
{
    {OperandType.InlineBrTarget, 4},
    {OperandType.InlineField, 4},
    {OperandType.InlineI, 4},
    {OperandType.InlineI8,8},
    {OperandType.InlineMethod,4},
    {OperandType.InlineNone,0},
    {OperandType.InlineR,8},
    {OperandType.InlineSig,4},
    {OperandType.InlineString,4},
    {OperandType.InlineSwitch,4},
    {OperandType.InlineTok,4},
    {OperandType.InlineType,4},
    {OperandType.InlineVar,2},
    {OperandType.ShortInlineBrTarget,1},
    {OperandType.ShortInlineI,1},
    {OperandType.ShortInlineR,4},
    {OperandType.ShortInlineVar,1}
};
-1
ответ дан 18 December 2019 в 14:48
поделиться

Here's a complete version of the correct answer. This uses material from other answers, but incorporates an important bugfix which no-one else spotted.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace Timwi.ILReaderExample
{
    public class ILReader
    {
        public class Instruction
        {
            public int StartOffset { get; private set; }
            public OpCode OpCode { get; private set; }
            public long? Argument { get; private set; }
            public Instruction(int startOffset, OpCode opCode, long? argument)
            {
                StartOffset = startOffset;
                OpCode = opCode;
                Argument = argument;
            }
            public override string ToString()
            {
                return OpCode.ToString() + (Argument == null ? string.Empty : " " + Argument.Value);
            }
        }

        private Dictionary<short, OpCode> _opCodeList;

        public ILReader()
        {
            _opCodeList = typeof(OpCodes).GetFields().Where(f => f.FieldType == typeof(OpCode)).Select(f => (OpCode) f.GetValue(null)).ToDictionary(o => o.Value);
        }

        public IEnumerable<Instruction> ReadIL(MethodBase method)
        {
            MethodBody body = method.GetMethodBody();
            if (body == null)
                yield break;

            int offset = 0;
            byte[] il = body.GetILAsByteArray();
            while (offset < il.Length)
            {
                int startOffset = offset;
                byte opCodeByte = il[offset];
                short opCodeValue = opCodeByte;
                offset++;

                // If it's an extended opcode then grab the second byte. The 0xFE prefix codes aren't marked as prefix operators though.
                if (opCodeValue == 0xFE || _opCodeList[opCodeValue].OpCodeType == OpCodeType.Prefix)
                {
                    opCodeValue = (short) ((opCodeValue << 8) + il[offset]);
                    offset++;
                }

                OpCode code = _opCodeList[opCodeValue];

                Int64? argument = null;

                int argumentSize = 4;
                if (code.OperandType == OperandType.InlineNone)
                    argumentSize = 0;
                else if (code.OperandType == OperandType.ShortInlineBrTarget || code.OperandType == OperandType.ShortInlineI || code.OperandType == OperandType.ShortInlineVar)
                    argumentSize = 1;
                else if (code.OperandType == OperandType.InlineVar)
                    argumentSize = 2;
                else if (code.OperandType == OperandType.InlineI8 || code.OperandType == OperandType.InlineR)
                    argumentSize = 8;
                else if (code.OperandType == OperandType.InlineSwitch)
                {
                    long num = il[offset] + (il[offset + 1] << 8) + (il[offset + 2] << 16) + (il[offset + 3] << 24);
                    argumentSize = (int) (4 * num + 4);
                }

                // This does not currently handle the 'switch' instruction meaningfully.
                if (argumentSize > 0)
                {
                    Int64 arg = 0;
                    for (int i = 0; i < argumentSize; ++i)
                    {
                        Int64 v = il[offset + i];
                        arg += v << (i * 8);
                    }
                    argument = arg;
                    offset += argumentSize;
                }

                yield return new Instruction(startOffset, code, argument);
            }
        }
    }

    public static partial class Program
    {
        public static void Main(string[] args)
        {
            var reader = new ILReader();
            var module = typeof(Program).Module;
            foreach (var instruction in reader.ReadIL(typeof(Program).GetMethod("Main")))
            {
                string arg = instruction.Argument.ToString();
                if (instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldflda || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldsflda || instruction.OpCode == OpCodes.Stfld)
                    arg = module.ResolveField((int) instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt)
                    arg = module.ResolveMethod((int) instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Newobj)
                    // This displays the type whose constructor is being called, but you can also determine the specific constructor and find out about its parameter types
                    arg = module.ResolveMethod((int) instruction.Argument).DeclaringType.FullName;
                else if (instruction.OpCode == OpCodes.Ldtoken)
                    arg = module.ResolveMember((int) instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Ldstr)
                    arg = module.ResolveString((int) instruction.Argument);
                else if (instruction.OpCode == OpCodes.Constrained || instruction.OpCode == OpCodes.Box)
                    arg = module.ResolveType((int) instruction.Argument).FullName;
                else if (instruction.OpCode == OpCodes.Switch)
                    // For the 'switch' instruction, the "instruction.Argument" is meaningless. You'll need extra code to handle this.
                    arg = "?";
                Console.WriteLine(instruction.OpCode + " " + arg);
            }
            Console.ReadLine();
        }
    }
}
4
ответ дан 18 December 2019 в 14:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: