我正在用C#开发一个库,该库使用System.Reflection.Emit.TypeBuilder
类生成运行时类型,并且我想生成以下类层次结构:
[XmlInclude(typeof(Derived))]
public class Base
{
}
public class Derived : Base
{
}
我通过以下方式使用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>();
}
}
电话:
var attribute = baseType.GetCustomAttribute<XmlIncludeAttribute>();
我收到以下错误:
无法加载文件或程序集“测试,版本= 0.0.0.0,区域性=中性,公共(public) key token =空”或其依赖项之一。该系统找不到指定的文件。
任何想法都很容易理解:我如何在TypeBuilder的基类上应用自定义属性,该基类引用派生类的TypeBuilder?
P.S:我正在使用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;
}
}