(如何)我可以查询类“;“建造后”;,在C#Net中使用反射?

(如何)我可以查询类“;“建造后”;,在C#Net中使用反射?,c#,reflection,runtime,build-process,C#,Reflection,Runtime,Build Process,情景: 我在一个VisualStudio项目中有一个.cs文件列表(例如MyPOCOs),其中包含一堆POCOs(普通的旧C#对象) 我必须运行一个定制的序列化工具(国产的,我可以访问源代码),将这些POCO转换成XML文件——该工具通过反射来实现这一点 目前,MyPOCOs项目被标记为控制台应用程序,其主要方法如下: class Program { static void Main(string[] args) { //In

情景:

  • 我在一个VisualStudio项目中有一个.cs文件列表(例如MyPOCOs),其中包含一堆POCOs(普通的旧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项目的“构建”相结合,但我不确定每个人都能理解此方法的可行性。因此,当我们在VisualStudio中“构建”项目时,上述
Main
方法本质上得到了执行。以下是我在这种方法中看到的两个问题:

  • 如何发现要序列化的类?目前,我通过
    AddPocoModel
    方法将它们添加到main方法中。但是如果我不这样做,我怎么能发现它们并通过反射来查询它们呢
  • 我如何在构建后触发上述主方法(即,它可以是自定义类中的任何方法。我只是使用
    main
    作为参数。基本上,我如何触发执行上述主方法的方法)

  • 我如何做到这一点?或者,对于上述问题有更好的解决方案吗?

    我会将序列化程序分解成一个单独的项目,一个控制台应用程序就可以了。这个应用程序应该采用一个指向刚刚编译的DLL的参数,然后您可以创建一个运行此工具并传入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();
        }
    }
    
    “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();
        }
    }
    
    公共类POCOSerializer
    {
    公共静态void序列化(字符串dllFileName,GenerateBulkVmXML batchSerializer)
    {
    var assem=Assembly.LoadFrom(dllFileName);
    var pocoObjects=assem.GetTypes(),其中(t=>t.GetCustomAttribute()!=null);
    foreach(PocoObject中的var poco)
    {
    AddPocoModel(poco,poco.Namespace);
    }
    batchSerializer.WriteXML();
    }
    }
    
    我非常喜欢这种方法,我倾向于采用这种方法。我希望构建团队不要否决这一点,因为目前所有的项目都不是控制台应用程序,而是类库。如果控制台应用程序不是一个选项,你有其他想法吗?只是一个想法:)(PS:目前POCO使用自定义属性进行注释,所以这是一个加号:)如果没有加载和运行的东西,任意代码实际上是不“可运行”的。当你创建一个exe项目时,编译器会添加相应的入口点和跳转。您可以创建一个运行“main”方法的工具,但不能只告诉生成后操作在DLL中运行某个方法。如果一个构建团队不允许使用某种定制工具,那么我会遇到一个大问题。构建后的事件具体会写在哪里?要为其触发工具的项目的
    .csproj
    文件?这就是我目前在理解这种方法的实现方面的差距——据我所知,您是在谈论可以使用Visual Studio的WYSIWYG编辑器(项目>属性>生成事件)配置的生成前/生成后事件吗?这是正确的,生成操作最终会出现在.csproj文件中。WYSIWYG是编辑它们的一种方法,但如果您使用的是不同的生成系统,则根据生成工具的不同,还有其他方法可以运行生成后操作。是的,只要您所反映的DLL引用了DLL,就应该能够在必要时加载它。控制台应用程序不需要对正在序列化的DLL或其任何依赖项的引用,只要DLL的依赖项在加载时是可发现的。