【发布时间】:2010-08-07 22:27:16
【问题描述】:
我正在尝试重现 System.Xml.Serialization 已经做过的事情,但是用于不同的数据源。 目前任务仅限于反序列化。 IE。给定我知道如何阅读的已定义数据源。编写一个采用随机类型的库,通过反射了解它的字段/属性,然后生成并编译可以获取数据源和该随机类型的实例的“读取器”类,并从数据源写入对象的字段/属性。
这是我的 ReflectionHelper 类的简化摘录
public class ReflectionHelper
{
public abstract class FieldReader<T>
{
public abstract void Fill(T entity, XDataReader reader);
}
public static FieldReader<T> GetFieldReader<T>()
{
Type t = typeof(T);
string className = GetCSharpName(t);
string readerClassName = Regex.Replace(className, @"\W+", "_") + "_FieldReader";
string source = GetFieldReaderCode(t.Namespace, className, readerClassName, fields);
CompilerParameters prms = new CompilerParameters();
prms.GenerateInMemory = true;
prms.ReferencedAssemblies.Add("System.Data.dll");
prms.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().GetModules(false)[0].FullyQualifiedName);
prms.ReferencedAssemblies.Add(t.Module.FullyQualifiedName);
CompilerResults compiled = new CSharpCodeProvider().CompileAssemblyFromSource(prms, new string[] {source});
if (compiled.Errors.Count > 0)
{
StringWriter w = new StringWriter();
w.WriteLine("Error(s) compiling {0}:", readerClassName);
foreach (CompilerError e in compiled.Errors)
w.WriteLine("{0}: {1}", e.Line, e.ErrorText);
w.WriteLine();
w.WriteLine("Generated code:");
w.WriteLine(source);
throw new Exception(w.GetStringBuilder().ToString());
}
return (FieldReader<T>)compiled.CompiledAssembly.CreateInstance(readerClassName);
}
private static string GetFieldReaderCode(string ns, string className, string readerClassName, IEnumerable<EntityField> fields)
{
StringWriter w = new StringWriter();
// write out field setters here
return @"
using System;
using System.Data;
namespace " + ns + @".Generated
{
public class " + readerClassName + @" : ReflectionHelper.FieldReader<" + className + @">
{
public void Fill(" + className + @" e, XDataReader reader)
{
" + w.GetStringBuilder().ToString() + @"
}
}
}
";
}
}
和调用代码:
class Program
{
static void Main(string[] args)
{
ReflectionHelper.GetFieldReader<Foo>();
Console.ReadKey(true);
}
private class Foo
{
public string Field1 = null;
public int? Field2 = null;
}
}
动态编译当然会失败,因为 Foo 类在 Program 类之外是不可见的。但! .NET XML 反序列化程序以某种方式解决了这个问题——问题是:如何? 通过反射器挖掘 System.Xml.Serialization 一个小时后,我开始接受我在这里缺乏一些基本知识并且不确定我在寻找什么......
另外,我完全有可能在重新发明轮子和/或朝错误的方向挖掘,在这种情况下,请大声说出来!
【问题讨论】:
-
您遇到了哪些错误,报告在哪里?
-
CompileAssemblyFromSource()返回稍后由throw new Exception(w.GetStringBuilder().ToString());抛出的错误。我回家后会检查确切的消息,但基本上归结为“Foo 类不可见”
标签: c# .net reflection assemblies