Tim*_*nem 12 .net c# reflection reflection.emit
我正在用C#开发一个库,它使用System.Reflection.Emit.TypeBuilder类生成运行时类型,我想生成以下类层次结构:
[XmlInclude(typeof(Derived))]
public class Base
{
}
public class Derived : Base
{
}
Run Code Online (Sandbox Code Playgroud)
我以下列方式使用TypeBuilder类:
class Program
{
public static void Main(string[] args)
{
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.Run);
var moduleBuilder = assembly.DefineDynamicModule("Test");
var baseTypeBuilder = moduleBuilder.DefineType("Base", TypeAttributes.Public, typeof(Object));
var derivedTypeBuilder = moduleBuilder.DefineType("Derived", TypeAttributes.Public);
derivedTypeBuilder.SetParent(baseTypeBuilder);
baseTypeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(XmlIncludeAttribute).GetConstructor(new[] { typeof(Type) }), new[] { derivedTypeBuilder }));
var baseType = baseTypeBuilder.CreateType();
var derivedType = derivedTypeBuilder.CreateType();
var attribute = baseType.GetCustomAttribute<XmlIncludeAttribute>();
}
}
Run Code Online (Sandbox Code Playgroud)
电话:
var attribute = baseType.GetCustomAttribute<XmlIncludeAttribute>();
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
无法加载文件或程序集'Test,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'或其依赖项之一.该系统找不到指定的文件.
任何想法都很受欢迎:如何在TypeBuilder上为引用类引用TypeBuilder的基类应用自定义属性?
PS:我使用的是Visual Studio 2017(v15.7.5)和C#类库(.NET Framework项目模板),而不是.NET Core或.NET Standard
无法提供太多理由,但解决方案无需额外加载/卸载或任何来自磁盘的工作:
添加一个包含实际的单独字段Assembly,可以只订阅AppDomain.CurrentDomain.AssemblyResolve并检查是否请求了动态程序集.
如果是的话,你只需要返回你的领域,它就可以完美地运行.
例:
class Program
{
static Assembly ass;
public static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.Run);
var moduleBuilder = assembly.DefineDynamicModule("Test");
var baseTypeBuilder = moduleBuilder.DefineType("Base", TypeAttributes.Public, typeof(Object));
var derivedTypeBuilder = moduleBuilder.DefineType("Derived", TypeAttributes.Public);
derivedTypeBuilder.SetParent(baseTypeBuilder);
baseTypeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(XmlIncludeAttribute).GetConstructor(new[] { typeof(Type) }), new[] { derivedTypeBuilder }));
var baseType = baseTypeBuilder.CreateType();
var derivedType = derivedTypeBuilder.CreateType();
ass = baseType.Assembly;
var attribute = baseType.GetCustomAttribute<XmlIncludeAttribute>();
Console.WriteLine(attribute.Type.FullName);
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return ass;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经重现了你的异常。.NET Framework 似乎想要从磁盘读取模块。
因此,最简单的解决方法是将程序集保存到磁盘:
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("Test"),
AssemblyBuilderAccess.RunAndSave); // allow run & save
var moduleBuilder = assembly.DefineDynamicModule("Test",
"Test.dll"); // specify a file name where module will be stored
...
var baseType = baseTypeBuilder.CreateType();
var derivedType = derivedTypeBuilder.CreateType();
assembly.Save("Test.dll");
Run Code Online (Sandbox Code Playgroud)
现在我能够毫无例外地获取属性:
var attribute = baseType.GetCustomAttribute<XmlIncludeAttribute>();
Run Code Online (Sandbox Code Playgroud)