- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设我有一个 SpaceShip
类,如下所示:
public class SpaceShip {
public SpaceShip() { }
public SpaceShip(IRocketFuelSource fuelSource) { }
}
我想使用 TypeBuilder
在运行时创建一个继承自 SpaceShip 的类型,并为 SpaceShip 中的每个类型定义一个构造函数。除了将参数传递给父级(“直通”构造函数)之外,我不需要构造函数实际做 任何事情。例如,如果用 C# 表示,生成的类型将如下所示:
public class SpaceShipSubClass : SpaceShip {
public SpaceShipSubClass() : base() { }
public SpaceShipSubClass(IRocketFuelSource fuelSource) : base(fuelSource) { }
}
让事情有点复杂的是,直到运行时我才真正知道生成的类型将从哪个类继承(所以我必须考虑任意数量的构造函数,可能带有默认参数)。
这可能吗?我想如果我有一个大致的开始方向,我可以弄明白,只是我对 TypeBuilder
是全新的。
谢谢!
最佳答案
好吧,我在网上找不到任何东西,所以我最终实现了自己的。这也应该有助于开始编写某种代理的任何人。
public static class TypeBuilderHelper
{
/// <summary>Creates one constructor for each public constructor in the base class. Each constructor simply
/// forwards its arguments to the base constructor, and matches the base constructor's signature.
/// Supports optional values, and custom attributes on constructors and parameters.
/// Does not support n-ary (variadic) constructors</summary>
public static void CreatePassThroughConstructors(this TypeBuilder builder, Type baseType)
{
foreach (var constructor in baseType.GetConstructors()) {
var parameters = constructor.GetParameters();
if (parameters.Length > 0 && parameters.Last().IsDefined(typeof(ParamArrayAttribute), false)) {
//throw new InvalidOperationException("Variadic constructors are not supported");
continue;
}
var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
var requiredCustomModifiers = parameters.Select(p => p.GetRequiredCustomModifiers()).ToArray();
var optionalCustomModifiers = parameters.Select(p => p.GetOptionalCustomModifiers()).ToArray();
var ctor = builder.DefineConstructor(MethodAttributes.Public, constructor.CallingConvention, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
for (var i = 0; i < parameters.Length; ++i) {
var parameter = parameters[i];
var parameterBuilder = ctor.DefineParameter(i + 1, parameter.Attributes, parameter.Name);
if (((int)parameter.Attributes & (int)ParameterAttributes.HasDefault) != 0) {
parameterBuilder.SetConstant(parameter.RawDefaultValue);
}
foreach (var attribute in BuildCustomAttributes(parameter.GetCustomAttributesData())) {
parameterBuilder.SetCustomAttribute(attribute);
}
}
foreach (var attribute in BuildCustomAttributes(constructor.GetCustomAttributesData())) {
ctor.SetCustomAttribute(attribute);
}
var emitter = ctor.GetILGenerator();
emitter.Emit(OpCodes.Nop);
// Load `this` and call base constructor with arguments
emitter.Emit(OpCodes.Ldarg_0);
for (var i = 1; i <= parameters.Length; ++i) {
emitter.Emit(OpCodes.Ldarg, i);
}
emitter.Emit(OpCodes.Call, constructor);
emitter.Emit(OpCodes.Ret);
}
}
private static CustomAttributeBuilder[] BuildCustomAttributes(IEnumerable<CustomAttributeData> customAttributes)
{
return customAttributes.Select(attribute => {
var attributeArgs = attribute.ConstructorArguments.Select(a => a.Value).ToArray();
var namedPropertyInfos = attribute.NamedArguments.Select(a => a.MemberInfo).OfType<PropertyInfo>().ToArray();
var namedPropertyValues = attribute.NamedArguments.Where(a => a.MemberInfo is PropertyInfo).Select(a => a.TypedValue.Value).ToArray();
var namedFieldInfos = attribute.NamedArguments.Select(a => a.MemberInfo).OfType<FieldInfo>().ToArray();
var namedFieldValues = attribute.NamedArguments.Where(a => a.MemberInfo is FieldInfo).Select(a => a.TypedValue.Value).ToArray();
return new CustomAttributeBuilder(attribute.Constructor, attributeArgs, namedPropertyInfos, namedPropertyValues, namedFieldInfos, namedFieldValues);
}).ToArray();
}
}
用法(假设您有一个 TypeBuilder
对象——参见 here 的示例):
var typeBuilder = ...; // TypeBuilder for a SpaceShipSubClass
typeBuilder.CreatePassThroughConstructors(typeof(SpaceShip));
var subType = typeBuilder.CreateType(); // Woo-hoo, proxy constructors!
关于c# - 使用 TypeBuilder 为基类创建传递构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6879279/
我正在业余时间开发一个交互式编译器,我发现我可以使用 TypeBuilder 定义一个类型,它定义两个具有相同名称的字段(并且该类型显然会发出并运行它的初始化程序,这些静态字段在其中初始化,就好了)。
我在业余时间研究交互式编译器,我发现我可以使用 TypeBuilder 定义一个类型,它定义了两个具有相同名称的字段(并且该类型显然会发出并运行它的初始化器,其中初始化这些静态字段,就好了)。查看我的
我有一个帮助程序类,它使用 TypeBuilder 来构造动态类型。它的用法如下: var tbh = new TypeBuilderHelper("MyType"); tbh.AddProperty
我正在创建一个 WCF Web 服务。 我正在尝试根据从数据库返回的信息创建一个类型,用数据构建一个类型列表,然后将其发回。 但是,我得到了一个 Type 'MyDynamicType' with d
假设我有一个 SpaceShip 类,如下所示: public class SpaceShip { public SpaceShip() { } public SpaceShip(I
我正在尝试基于仅包含公共(public)字段的现有类型创建动态类型。新的动态类型还必须继承自仅具有完全实现方法的不同基类型。 我创建了指定基类型的 TypeBuilder,然后我将公共(public)
我有一些代码使用在生成类型上找到的泛型方法的 MethodInfo。为了避免一些反射(reflection),我让代码使用 ldtoken Method ldtoken Type call GetMe
如何检查 Type 对象是否为 TypeBuilderInstantiation? 基本上,我需要一个脱离 Type 的方法。 如果是 TypeBuilderInstantiation,我需要调用 T
我发出了几个类,其中一些需要在自己的构造函数中构造它们的对等体。不存在无限递归依赖(因此如果 A 构造 B,B 将不会构造 A;这对于嵌套引用也是如此 [A 构造 B 构造 C 意味着 B 和 C 都
请帮我在 DisplayAttribute 中添加我尝试过的属性,但将 consturtor 错误设置为 null var fieldName = string.Format(
尝试将应用程序从 .net 4.5 移植到客户端的 .net 核心。我注意到 CreateType 不再是 TypeBuilder 的一部分。我搜索了多个新的反射库,但没有成功。有谁知道如何移植这个?
我正在用 C# 开发一个库,它使用 System.Reflection.Emit.TypeBuilder 类生成运行时类型,我想生成以下类层次结构: [XmlInclude(typeof(Derive
我需要在运行时使用 TypeBuilder 创建一个类型。这种类型应该实现一个特定的接口(interface),以便可以在编译时统一处理这种动态类型的实例。 该接口(interface)应返回一个对象
我想将在运行时生成的类型(通过 TypeBuilder)传递给泛型类中的泛型方法。我不能将它作为对象传递,因为反射用于查找各种属性。 据我所知,这无法完成,因为泛型是在编译时而不是运行时应用的。 我知
我想使用 TypeBuilder 构建一个与接口(interface)匹配的类型。它的基类型将是对象,因为我没有任何抽象点。 有问题的接口(interface)有一个像这样的属性:: public i
我正在使用 Reflection.Emit 制作一个 .NET 兼容的编译器。问题是,虽然 TypeBuilder 是从 Type 派生的,但它不允许我使用 Type 提供的所有方便的方法。 我真正关
我正在创建一个动态 dll 来保存从我的数据库创建的自定义对象。我可以按照我想要的方式创建字段,但是我不明白如何调用构造函数。对于最终生成的结果,我想要: public class Countries
我想在运行时创建类型并通过 Activator.CreateInstance 实例化它。我正在使用 Refletion.Emit 来执行此操作,当创建和实例化类型的方法在单个线程中运行时,一切正常。然
在开始之前,这是我关于 SO 的第一个问题。因此,可能存在错误或缺少有关该问题的信息。如果我需要更正某些内容,请告诉我。谢谢。 使用 TypeBuilder,我正在构建一个实现包含方法的接口(inte
我是一名优秀的程序员,十分优秀!