У меня этот класс:
public class Foo
{
public string Name { get; private set; }
}
Если я напишу это:
Foo foo = new Foo();
foo.Name = "Nocigar";
Очевидно, я получаю ошибку компилятора. Но если я напишу это:
static void Main()
{
Foo foo = new Foo();
Action<Foo, string> act = Build();
act(foo, "Woot");
Debug.WriteLine(foo.Name);
}
static Action<Foo, string> Build()
{
ParameterExpression fooParam =
Expression.Parameter(typeof(Foo),
"foo");
ParameterExpression nameParam =
Expression.Parameter(typeof(string),
"name");
MemberExpression propertyValue =
Expression.Property(fooParam,
"Name");
BinaryExpression assignExpression =
Expression.Assign(propertyValue,
nameParam);
LambdaExpression lambda =
Expression.Lambda(typeof(Action<Foo, string>),
assignExpression,
fooParam,
nameParam);
return (Action<Foo, string>)lambda.Compile();
}
Он компилируется и запускается без проблем, записывая "Woot" в окно отладки. Что дает?
Я намереваюсь использовать эту функцию в некотором коде для отображения из устройства чтения данных в POCO. Я обеспокоен тем, что это может быть побочным эффектом, а не предполагаемым поведением, и задаться вопросом, может ли кто-нибудь пролить свет на причины этого.
Это не побочный эффект. С отражением или выражениями вы можете получить доступ к таким частным членам, как это, например:
var dateTimeType = typeof (DateTime);
MethodInfo[] privateMthods = dateTimeType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static);
privateMthods.ToList().ForEach(a=> Console.WriteLine(a.Name.ToString()));
Как написано в книге "Метапрограммирование в.NET" Кевина Хаззарда и Джейсона Бока
"Theres также значение NonPublic, что означает, что вы можете видеть частный и защищенный контент через Reflection API. В зависимости от вашего представления это может показаться серьезным нарушением безопасности, если учесть, что это позволяет произвольному коду изменять значения частных полей в объекте, но только привилегированный код может использовать вызовы отражения. Если у вас нет такого уровня доступа, ваше использование рефлекса не удастся ". -page 46
Вы можете также рассмотреть это (опять же из вышеупомянутой книги):
"Как вы, вероятно, уже догадались с приложением Windows 8 и его моделью безопасности, вы можете получать доступ только к открытым членам, вы не можете получить доступ к закрытым членам. Опять же, эти изменения строго предназначены для приложений Windows 8. Если вы планируете использовать.NET 4.5 вне Windows 8, вы можете использовать полный класс Type. " - стр. 318
Эта статья также полезна: соображения безопасности для отражения
Reflection.Emit
но доступ к элементу ограничен только компилятором во время компиляции (это выполняется только во время выполнения только для сигнатуры метода), тогда с помощью выражений вы обойдете эту проверку (как вы можете сделать, используя сырое отражение).