我正在用C#编写一个简单的桌面客户端/服务器应用程序.出于自学目的,我为通过tcp/ip套接字连接在两个应用程序之间来回发送的消息(定义为类)构建了自己的序列化系统.系统在初始化时使用反射,通过发出IL来为每种消息类型构造序列化/反序列化方法.
该系统的第一个版本使用DynamicMethod,将true传递给构造函数以允许生成的IL(在消息类型中的任意字段上操作)忽略访问权限.这很有效,人们欢欣鼓舞,但我不满意不透明的调试结果函数是多么痛苦.所以我决定放弃DynamicMethod并使用*Builder类构建一个动态程序集,我可以选择将其保存到磁盘并使用.NET Reflector等工具进行检查.
我重构了系统,然后打了一个砖墙.每当其中一个新的序列化函数尝试访问我的某个消息类型中的私有字段或方法时,我都会收到FieldAccessException或MethodAccessException.经过大量谷歌搜索和咬牙切齿之后,我想我已经将问题缩小到一个权限; 特别是我认为我动态创建的程序集缺少相对于调用/构造程序集的ReflectionPermissionFlag.MemberAccess权限(所有反射类型都在这里).
不幸的是,我似乎无法弄清楚如何修改动态程序集创建过程,以便程序集具有反射权限回到创建程序集中.DefineDynamicAssembly的权限参数似乎与限制权限相关,而不是授予权限,这使我们留下了Evidence参数.证据似乎神奇地转化为一组权限,但我找不到任何有用的例子或解释这是如何发生的.
所以我的问题是:
(1)我是否认为我的问题是对动态创建的程序集缺乏权限?
(2)如果是这样,作为调用程序集,我如何为动态程序集授予必要的权限?
当前的动态程序集创建代码:
AssemblyName assembly_name = new AssemblyName( "LCSerialization" );
assembly_name.Version = new Version( 1, 0, 0, 0 );
m_SerializationAssembly = current_domain.DefineDynamicAssembly( assembly_name, AssemblyBuilderAccess.RunAndSave ); // Fix me
m_SerializationModule = m_SerializationAssembly.DefineDynamicModule( "MainModule", "LCSerialization.dll" );
m_SerializationWrapperClass = m_SerializationModule.DefineType( "CSerializationWrapper", TypeAttributes.Public );
Run Code Online (Sandbox Code Playgroud)
请注意,我的项目是针对.NET 3.5; 文档声称.NET 4.0使用不同的安全性概念,并且不推荐使用DefineDynamicAssembly中的Evidence/PemissionSet方法.
举一个具体的例子,假设我有一个类:
[NetworkMessage]
public class CTestMessage
{
public CTestMessage( int cheeseburgers )
{
m_CheeseBurgers = cheeseburgers
}
private int m_CheeseBurgers = 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我的序列化系统,在初始化反射期间遇到这种情况时,大致会以类型= typeof(CTestMessage)粗略地完成(剪切和粘贴不可能在这里)以下内容:
MethodBuilder …Run Code Online (Sandbox Code Playgroud)