. net Framework 4.7.2 ...
Скомпилированные выражения могут получить доступ к закрытым полям. Когда я использую точно такое же выражение и записываю его в динамическую сборку c, используя CompileToMethod
, я получаю System.FieldAccessException
при попытке прочитать приватное поле.
Могу ли я что-нибудь сделать, чтобы сборка Dynami c имела те же привилегии доступа, что и скомпилированное выражение? Есть древние знания, которые говорят, что вы не можете. Но я не могу найти ничего похожего на первоисточник этого утверждения. Я не могу поверить, что не существует какой-либо формы атрибутов сборки или разрешений, которые позволили бы получить доступ.
Можно ли это сделать, если вместо этого сохранить сборку? (Запись кэшированных сборок на диск является вероятной особенностью в будущем.)
Приложение сортирует структуры в потоки на языке c computer musi c, определяемом доменом. Сериализация не является опцией (еще один пример динамического c кода в динамических c сборках, который нарушает доступ).
Пример кода:
Лямбда-выражение успешно считывает значение частного поля ComplexStruct (приведено ниже). Если одно и то же выражение отправляется в динамическую сборку c с использованием CompileToMethod, оно завершается с ошибкой доступа.
ComplexStruct s = new ComplexStruct();
s.String1 = "abc";
// Pick a private field (one of the backing fields for a property)
FieldInfo fieldInfo = typeof(ComplexStruct).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)[0];
var structArgument = Expression.Parameter(typeof(ComplexStruct));
var lambda = Expression.Lambda<Func<ComplexStruct,String>>(
Expression.Field(structArgument, fieldInfo), // return the value of the private field.
structArgument);
Func<ComplexStruct,String> fn = lambda.Compile();
String result = fn(s);
Assert.AreEqual(structArgument.String1, result);
Структура с закрытыми полями:
// (Complex compared to simple struct where all fields
// are public or the struct is unmanaged in case you were wondering)
public struct ComplexStruct : IEquatable<ComplexStruct>
{
public String String1 { get; set; } // the backing field for this property gets read.
public String String2 { get; set; }
public String String3 { get; }
public ComplexStruct(String v1, String v2)
{
String1 = v1;
String2 = v2;
}
public bool Equals(ComplexStruct other)
{
return String1 == other.String1 && String2 == other.String2;
}
}
Создание сборка:
AppDomain myAppDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "DynamicAssembly";
this.saveAssembly = ServiceBase.DEBUG;
assemblyBuilder = myAppDomain.DefineDynamicAssembly(
myAsmName,
saveAssembly? AssemblyBuilderAccess.RunAndSave: AssemblyBuilderAccess.RunAndCollect);