(如何)是否可以在 C#.Net 中使用反射查询类“后期生成”

本文关键字:查询 反射 后期生成 是否 如何 Net | 更新日期: 2023-09-27 18:19:17

场景:

  • 我有一个Visual Studio项目(例如MyPOCO(中的.cs文件列表,其中包含一堆POCO(普通的旧C#对象(
  • 必须运行一个自定义序列化工具(自制的,我可以访问源代码(,将这些 POCO 转换为 XML 文件 - 该工具通过反射来做到这一点。

目前,MyPOCOs项目被标记为控制台应用程序,并具有如下所示的主方法:

class Program
    { 
        static void Main(string[] args)
        {
            //Initialize custom XML Serializer
            GenerateBulkVmXML batchSerializer = new GenerateBulkVmXML();
            //Add individual POCOs to Serializer
            batchSerializer.AddPocoModel(typeof(MyPOCO1), "My.Custom.NameSpace");
            batchSerializer.AddPocoModel(typeof(MyPOCO2), "My.Custom.NameSpace1");
            batchSerializer.AddPocoModel(typeof(MyPOCO3), "My.Custom.NameSpace2");
            //Generate custom XML
            batchSerializer .WriteXML(); 
        }
}

每次我们"运行"上述控制台应用程序时,它都会触发Main方法,该方法通过反射查询 POCO 类并喷出 XML。

问题:对于添加到项目中的每个新 POCO,我们都在上述Main方法中添加了一行,通过传递新创建的 POCO 的类型来调用 batchSerializer.AddPocoModel(...) 方法。随着时间的流逝,POCO的数量将增加,这很好变得相当笨拙。

建议

的解决方案:我的团队建议我们将此过程与MyPOCO项目的"构建"集成,但我不确定每个人都能掌握这种方法的可行性。因此,当我们在Visual Studio中"构建"项目时,实质上会执行上述Main方法。以下是我在这种方法中看到的两个问题:

  1. 如何发现要序列化的类?目前,我通过AddPocoModel方法将它们添加到主方法中。但是,如果我不这样做,我如何通过反射发现它们并查询它们?
  2. 究竟如何在构建后触发上述 main 方法(即,它可以是自定义类中的任何方法。我只是为了争论而使用Main。基本上,我如何触发执行上述主要方法的方法(?

我如何实现这一点?或者,有没有更好的解决方案来解决上述问题?

(如何)是否可以在 C#.Net 中使用反射查询类“后期生成”

我会将您的序列化程序分解为一个单独的项目,控制台应用程序就可以了。此应用程序应采用指向刚编译的 DLL 的参数,然后可以创建运行此工具并传入 DLL 名称的生成后命令。从好的方面来说,这为其他项目创建了一个可重用的工具。有许多宏,但你的宏最终看起来像这样:

"c:'path'to'serialization'tool.exe" $(TargetPath)

至于发现类型,由于您的 POCO 模型类与其他类可能没有任何区别(如果 DLL 中有其他类(,因此您需要以某种方式标记它们。我会使用自定义属性:

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class SerializePOCOAttribute : Attribute { }

然后,可以使用发现方法来枚举 DLL 中的所有类并序列化它们,如下所示:

public class POCOSerializer
{
    public static void Serialize(string dllFileName, GenerateBulkVmXML batchSerializer)
    {
        var assem = Assembly.LoadFrom(dllFileName);
        var pocoObjects = assem.GetTypes().Where(t => t.GetCustomAttribute<SerializePOCOAttribute>() != null);
        foreach (var poco in pocoObjects)
        {
            batchSerializer.AddPocoModel(poco, poco.Namespace);
        }
        batchSerializer.WriteXML();
    }
}