(如何)我可以在 C#.Net 中使用反射查询 类 "post-build" 吗?

(How) Can I query classes "post-build", using reflection in C#.Net?

场景:

目前,MyPOCOs 项目被标记为 Console App 并且具有如下所示的主要方法:

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(); 
        }
}

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

问题:对于每一个新添加到项目中的POCO,我们都在上面的Main方法中添加一行调用batchSerializer.AddPocoModel(...)方法,通过传递他们输入新创建的 POCO。随着时间的推移,POCO 的数量会增加,这会变得相当笨重。

建议的解决方案:我的团队建议我们将此过程与 MyPOCO 项目的 "build" 集成,但我不确定每个人都能掌握这个的可行性方法。所以,当我们'build' visual studio 中的项目时,上面的Main 方法实际上被执行了。以下是我发现这种方法存在的两个问题:

  1. 我如何 发现要序列化的 classes?目前我通过 AddPocoModel 方法将它们添加到主要方法中。但是,如果我不这样做,我如何通过反射发现它们并查询它们?
  2. 我如何 触发上面的主要方法post-build(即,它可以是一个自定义 class。我只是为了争论而使用 Main。基本上,我如何触发 the 方法来完成 main 方法的功能以上)?

我该如何实现?或者,上面的问题有更好的解决办法吗?

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

"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();
    }
}