我有一个字符串列表,需要是属性名称,还有一个需要是类型名称的字符串。我将对象传递给第三方UI,它所关心的是它显示的类和字段名称(默认行为)。我可以实现一个接口来自定义返回的字符串,这样它们不仅仅是驼峰名称,还可以隐藏某些成员。
我看到了ExpandOObject,这不起作用,因为第三方无法在其上找到任何成员名称,因为它没有显示任何内容,也没有在其接口上调用该方法来替换具有有意义名称的字段访问者。
DynamicObject看起来更有前景,但我不确定如何实现这一点,并且没有看到一个简单的例子。
我想还有TypeBuilder,我从未使用过。
可以获得有关获取此Duck类型行为的一些指导。我假设第三方做了类似GetType()的事情。默认情况下是名字,所以这需要被拦截。它也必须使用反射来发现字段名称。它接受BindingSource中包含的类型的实例 - 这是从中读取字段名称和课程类型的地方。
答案 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);