动态类创建,包括动态类型名称

时间:2013-12-13 14:05:40

标签: c#

我有一个字符串列表,需要是属性名称,还有一个需要是类型名称的字符串。我将对象传递给第三方UI,它所关心的是它显示的类和字段名称(默认行为)。我可以实现一个接口来自定义返回的字符串,这样它们不仅仅是驼峰名称,还可以隐藏某些成员。

我看到了ExpandOObject,这不起作用,因为第三方无法在其上找到任何成员名称,因为它没有显示任何内容,也没有在其接口上调用该方法来替换具有有意义名称的字段访问者。

DynamicObject看起来更有前景,但我不确定如何实现这一点,并且没有看到一个简单的例子。

我想还有TypeBuilder,我从未使用过。

可以获得有关获取此Duck类型行为的一些指导。我假设第三方做了类似GetType()的事情。默认情况下是名字,所以这需要被拦截。它也必须使用反射来发现字段名称。它接受BindingSource中包含的类型的实例 - 这是从中读取字段名称和课程类型的地方。

2 个答案:

答案 0 :(得分:3)

如果你真的,真的想创建一个动态类型,你实际上可以。您从AppDomain.DefineDynamicAssembly开始,然后是这个小小的起始级别教程:http://msdn.microsoft.com/en-us/library/5kyyyeh2%28v=vs.110%29.aspx,或者这个更彻底的教程:http://www.codeproject.com/Articles/121568/Dynamic-Type-Using-Reflection-Emit。请注意,这是重要的事情。如果要添加代码,则需要发出IL汇编指令(如果需要属性,则需要执行此操作)。这并不难,因为你可以使用像Reflector这样的工具将任何东西反编译成IL,你可以复制它。

或者您可以编写C#代码(作为实际文本文件或使用CodeDom)并编译它。这是一个问候世界样本:http://msdn.microsoft.com/en-us/library/system.codedom.compiler.codedomprovider%28v=vs.110%29.aspx。它不那么硬核,你可能会有点甚至更轻松,但它在后台做了更多的工作。它不支持所有边缘情况,C#语言的所有功能。而且它更间接,因此与上述解决方案相比,您需要自己处理程序集引用并加载新的程序集文件。

您没有对原始问题或图书馆说太多,或者为什么事先不知道类型和属性名称。通常情况下,我会试着告诉你这样做:)。

答案 1 :(得分:1)

来自fejesjoco的非常有用的建议非常感谢,这是使用我需要的Reflection.Emit.TypeBuilder的简单,相对不可怕的解决方案:

 var assembly = new AssemblyName("FieldTypes");
 AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
 TypeBuilder typeBuilder = moduleBuilder.DefineType("DataObjects", TypeAttributes.Public | TypeAttributes.AutoClass | 
     TypeAttributes.AnsiClass |TypeAttributes.BeforeFieldInit, typeof(System.Object));
 foreach (var dataObject in layout.DatabaseInstance.DataSourceObjects)
 {
     FieldBuilder fieldBuilder = typeBuilder.DefineField(dataObject.TableName + "X", typeof(System.String), FieldAttributes.Private);
     PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(dataObject.TableName, PropertyAttributes.HasDefault, typeof(System.String), null);
     MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + dataObject.TableName, MethodAttributes.Public | 
         MethodAttributes.SpecialName |MethodAttributes.HideBySig, typeof(System.String), Type.EmptyTypes);
     ILGenerator randomPropertyGetterIL = propertyGetter.GetILGenerator();
     randomPropertyGetterIL.Emit(OpCodes.Ldarg_0);
     randomPropertyGetterIL.Emit(OpCodes.Ldfld, fieldBuilder);
     randomPropertyGetterIL.Emit(OpCodes.Ret);
     propertyBuilder.SetGetMethod(propertyGetter);
 }
 Type randomType = typeBuilder.CreateType();
 binding.DataSource = Activator.CreateInstance(randomType);