使用反射来生成类(以生成动态FileHelper类)

本文关键字:动态 FileHelper 反射 | 更新日期: 2023-09-27 18:25:29

我可以使用反射动态构建如下所示的类吗?没有方法,只有公共变量,有些具有自定义属性。

需要.Emit方法吗(从我所看到的情况来看,"Emit"看起来有点挑战性)。

我使用的是www.FileHelpers.net上的软件,它需要一个类。我所有的文件定义都在一个数据库表中,我想让一切都更动态(即,当文件中出现新列时,代码不会更改)。

[FileHelpers.DelimitedRecord(",")]
public class FileRow
{
    [FileHelpers.FieldQuoted('"', QuoteMode.OptionalForBoth)] 
    public string Borrower_First_Name;
    [FileHelpers.FieldQuoted('"', QuoteMode.OptionalForBoth)] 
    public string Borrower_Last_Name;
    public string Borrower_Email;
}

更新1:根据Vlad的回答,我需要参考DLL,以下是我的做法:

    // need to reference the FileHelpers.dll from our own .exe directory 
    string diskFilenameFileHelpersDLL = 
        System.IO.Path.GetDirectoryName(
           System.Reflection.Assembly.GetExecutingAssembly().Location) + 
           @"'FileHelpers.dll";

更新2:此外,在完成Vlad的建议后,这就是我调用FileHelper并循环结果的方式。我可能会把数据转移到一个列表中。

    Assembly assembly = compiledResult.CompiledAssembly;
    // Simple Data Test 
    lineContents = "John,Doe,jd123456@yahoo.com";
    FileHelperEngine engine = new FileHelperEngine(assembly.GetType("FileRow"));
    // FileRow[] FileRowArray = (FileRow[])engine.ReadString(lineContents);
    Object[] FileRowArray = engine.ReadString(lineContents);
    Object myObject = FileRowArray[0];  // only 1 row of data in this example 
    // Get the type handle of a specified class.
    Type myType = assembly.GetType("FileRow");
    // Get the fields of the specified class.
    FieldInfo[] myField = myType.GetFields();
    Console.WriteLine("'nDisplaying fields values:'n");
    for (int i = 0; i < myField.Length; i++)
    {
        Object objTest = myField.GetValue(i);
        string tempName = myField[i].Name;
        Object objTempValue = myField[i].GetValue(myObject);
        string tempValue = System.Convert.ToString(objTempValue);
        Console.WriteLine("The value of {0} is: {1}",
                            tempName, tempValue);
    }

使用反射来生成类(以生成动态FileHelper类)

如果你的代码以字符串的形式存储在数据库中,你可以这样做来创建一个程序集:

我之所以注释掉属性,是因为我没有它们的命名空间。我假设您有名称空间,需要将其添加到代码中进行编译。

代码在LINQPad中工作,因此您可以直接复制和粘贴。

using System;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
void Main()
{
    StringBuilder dc = new StringBuilder(512);
    dc.Append("public class FileRow");
    dc.Append("{");
    //dc.Append("[FileHelpers.FieldQuoted(''"', QuoteMode.OptionalForBoth)]");
    dc.Append("public string Borrower_First_Name;");
    //dc.Append("[FileHelpers.FieldQuoted(''"', QuoteMode.OptionalForBoth)]");
    dc.Append("public string Borrower_Last_Name;");
    dc.Append("public string Borrower_Email;");
    dc.Append("}");
    CompilerResults compiledResult = CompileScript(dc.ToString());
    if (compiledResult.Errors.HasErrors)
    {
        Console.WriteLine (compiledResult.Errors[0].ErrorText);
        throw new InvalidOperationException("Invalid Expression syntax");
    }
    Assembly assembly = compiledResult.CompiledAssembly;
    // This is just for testing purposes.
    FieldInfo field = assembly.GetType("FileRow").GetField("Borrower_First_Name");          
    Console.WriteLine (field.Name);         
    Console.WriteLine (field.FieldType);
}
public static CompilerResults CompileScript(string source) 
{ 
    CompilerParameters parms = new CompilerParameters(); 
    parms.GenerateExecutable = false; 
    parms.GenerateInMemory = true; 
    parms.IncludeDebugInformation = false; 
    CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp"); 
    return compiler.CompileAssemblyFromSource(parms, source); 
} 

您还可以使用CodeDOM动态生成类。欲了解更多信息,请访问

http://msdn.microsoft.com/en-us/library/ms404245.aspx