Да, возможно определить Ваши собственные учетные данные, не изменяя текущий код. Это требует маленькой части кода от Вашей части все же.
Создают блок, названный 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, который намного более легче.
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 ();
}
Вам необходимо получить 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 , которые вы
Отражение - это в первую очередь API для проверки метаданных. Что вы пытаетесь сделать, так это проверить необработанный IL, который не является поддерживаемой функцией отражения. Reflection просто возвращает IL в виде необработанного байта [], который необходимо проверить вручную.
@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}
};
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();
}
}
}