文件级别的配置? C#和反思?级别、文件

2023-09-03 08:21:04 作者:薄凉不过人心

我有十几个类的文件,我使用反射来生成它的数据。我想这可能是冷静,如果我有一个办法,在一次配置所有的类在该文件中。我怎么可以这样做?

I have a file with a dozen classes and i use reflection to generate data from it. I was thinking it may be cool if i had a way to configure all of the classes in that file at once. How might i do this?

-edit-似乎每个人都感到困惑。我下面贴一个可能的解决方案。

-edit- everyone seems confused. I posted a possible solution below.

欲数据附加到一个文件中。在使用反射我想看看是否基于数据集的文件,并改变行为存在的数据。在本例中的解决方案我使用反射来寻找MyConfig类。我可以使用属性来设置的配置数据,并用它来改变我的code中的行为。这将工作在每个命名空间基地。我想使它成为一个每个文件基地。有了这个解决方案,我必须预留一个类名或我需要搜索所有的变化,看看它是否被标记为配置类。我可以做其他的解决方案?我可能使用的app.config但我preFER设置数据源文件中,并想通过标记每个类别的手工属性对它进行设置(或者迫使他们承受)。

I want to attach data to a file. While using reflection i would like to see if data exist for that file and change behavior based on data set. In the example solution i use reflection to look for MyConfig class. I can use attributes to set the configuration data and use that to change the behavior of my code. This will work on a per namespace bases. I would like to make it a per file bases. With this solution i MUST reserve a class name or i need to search all changes and see if it is tagged as a configuration class. What other solutions can i do? I could possibly use app.config but i prefer to set the data in the source file and would like to NOT set it by tagging every class with attributes by hand (or force them to inherit).

推荐答案

如何可以得到所有的类在一个给定的文件

有可能得到在三种情况下的所有类在运行时给定的cs文件:

It is possible to get all the classes in a given .cs file at runtime under three circumstances:

您解析在构建时的cs文件和类在其中的列表添加到您的.dll(可能作为一种资源) 您船.cs文件本身并解析它在运行时 您编译debuggng信息和船舶.pdb文件

航运.PDB或的.cs用于此目的似乎是一个坏主意,所以我可能会用的解决方案#1去。这个答案的其余部分将告诉该怎么做。

Shipping a .pdb or .cs for this purpose seems like a bad idea, so I would probably go with solution #1. The rest of this answer will tell how to do it.

一个。 MSBuild的配置中包括程序集的资源类名列表

要做到这一点:

创建自定义MSBuild任务的项目。引用 Microsoft.Build.Framework 组装并创建 Microsoft.Build.Framework.Task 接受一个的自定义子类输入cs文件,解析它提取的类名(包括命名空间),并写入以逗号分隔的完整的类名到一个输出文件。

Create a custom MSBuild task project. Reference the Microsoft.Build.Framework assembly and create a custom subclass of Microsoft.Build.Framework.Task that takes an input .cs file, parses it to extract class names (including namespaces), and writes the full class names separated by commas to to an output file.

添加一个目标引用您的自定义MSBuild任务到主.csproj的。使用编译项目组进行输入,并把输出 EmbeddedResources 项目组中,给它的输出文件的名称像 $(IntermediateOutputPath)%(文件名)%(分机).classList`。

Add a Target referencing your custom MSBuild Task to your main .csproj. Use the Compile item group for input and put the output in the EmbeddedResources item group, giving it the output file a name like "$(IntermediateOutputPath)%(FileName)%(Extension).classList`".

添加的PropertyGroup 您的.csproj的附加您的自定义目标为 CoreCompileDependsOn 属性。

Add a PropertyGroup to your .csproj that appends your custom target to the CoreCompileDependsOn property.

乙。使用类名称列出找到的类给定文件

如果你这样做,你.classList文件将在您的项目标有编译(基本上所有的.cs或.vb文件),每个文件建立,然后嵌入到可执行文件。

If you do this, your .classList files will be built for every file in your project marked "Compile" (basically all your .cs or .vb files), and then embedded into the executable.

现在发现的所有类在一个给定的文件很简单:

Now finding all the classes in a given file is easy:

var classesInFile = 
  from className in assembly.GetManifestResourceStream(fileName + ".classList")
  select assembly.GetType(className)

上的一些构建步骤其他信息

下面是生成任务将是什么样子:

Here is what the build task would look like:

public BuildClassListsTask : Task
{
  public ITaskItem[] CompileFiles;
  public ITaskItem[] ClassListFiles;

  public override bool Execute()
  {
    for(int i=0; i<ClassListFiles.Count; i++)
      File.WriteAllText(ClassListFiles[i].ItemSpec,
        ExtractClassNames(
          File.ReadAllText(CompileFiles[i].ItemSpec)));
  }

  public string ExtractClassNames(string codeFile)
  {
    string namespacePrefix = "";
    var classNames = new List<string>();
    foreach(string line in codeFile.Split("\r\n").Select(line => line.Trim()))
      if(line.StartsWith("namespace "))
        namespacePrefix += line.Substring("namespace ".Length).Trim() + ".";
      else if(line.StartsWith("class "))
        classNames.Add(line.Substring("class ".Length).Trim());
    return string.Join(",", classNames);
  }
}

下面是目标看起来像在你的.csproj什么(或.vbproj):

Here is what the Target would look like in your .csproj (or .vbproj):

<UsingTask TaskName="BuildClassListsTask"
           AssemblyFile="BuildClassLists.dll" />

<Target Name="BuildClassLists"
  Inputs="@(Compile)"
  Outputs="@(EmbeddedResources)">

  <ItemGroup>
    <ClassListFiles Include="@(Compile->$(IntermediateOutputPath)`%(FileName)%(Extension).classList)" />
    <EmbeddedResources Include="@(ClassListFiles)" />
  </ItemGroup>

  <BuildClassListsTask
    CompileFiles="@(Compile)"
    ClassListFiles="@(ClassListFiles)" />

</Target>

和最后但并非最不重要的,CoreCompileDependsOn设置:

And last but not least, the CoreCompileDependsOn setting:

<PropertyGroup>
  <CoreCompileDependsOn>$(CoreCompileDependsOn);BuildClassLists</CoreCompileDependsOn>
</PropertyGroup>

以上code为刚刚输入了我的头顶,所以它可能不完全正确的。希望这会为你工作,虽然。

The above code is just typed off the top of my head, so it may not be exactly correct. Hopefully it will work for you, though.

最后说明

如果你想包括在运行时可在你的cs文件的其他数据,只是把它放在意见并适当修改上面的 ExtractClassNames 法提取的附加数据注释并将其包含在它的输出。

If you want to include additional data available at runtime in your .cs file, just put it in comments and suitably modify the ExtractClassNames method above to extract the additional data from the comments and include it in its output.

另一种可能性是使用上述技术,但修改通过在应用程序中的所有编译后的文件执行方法循环,​​并创建一个包含所有配置一个输出文件数据在应用程序中的所有文件,可能是XML格式。如果你这样做,你将包括在 EmbeddedResources 项目组中的一个输出文件,你可以硬code的名字。

Another possibility would be to use the above technique but change the Execute method to loop through all the compiled files in your application and create a single output file containing all the configuration data for all the files in your application, probably in an XML format. If you do this, you would include just the single output file in the EmbeddedResources item group, and you could hard-code its name.

第三种可能性是附上您的配置数据的任意类的cs文件的属性,让 .classNames 文件帮助你用所有的类关联在该文件。

A third possibility would be to attach your configuration data as attributes of an arbitrary class in the .cs file and let the .classNames file help you associate it with all classes in the file.

 
精彩推荐
图片推荐