尝试在c# w/Visual Studio 2010中创建自动版本控制系统

本文关键字:创建 控制系统 版本 2010 Studio Visual | 更新日期: 2023-09-27 17:55:04

所以我有一个大的类集合,当一个类被更新时,我需要对任何现有的保存数据运行一个更新方法。目前我使用的是:

public const decimal LatestVersion = 0.0121201313m;
private decimal LastVersion;
//...
if (Abilities.LastVersion != Abilities.LatestVersion)
{
    //...

并且我每次更新类时都手动更新LatestVersion号…我还必须在每个可能需要更新的类中重复这个方法。它工作得很好,但是我必须记得更新版本号。

我认为会很好是有最新版本自动更新到当前的DateTime(也许通过调试命令),如果类被改变或类似的东西…但我认为那是不可能的。

有没有人对我如何在类级别上设置自动实现版本控制系统有任何其他想法?

尝试在c# w/Visual Studio 2010中创建自动版本控制系统

您可以在一个版本的类文件中使用某种非空白内容的散列。每个类需要2个文件——一个源文件,一个在构建时生成的文件,但会保证任何更改都会更改版本。可能需要在散列中添加日期,以防万一。

 // source file MyClass.cs
 partial class MyClass {}

 // MyClass.Hash.cs
 // generate during build via custom tool 
 partial class MyClass 
 {
    // hash of MyClass.cs + date
    public static string LatestVersion = "W#$@WW-2012-01-22"; 
 }

指出:

  • 自动系统可能比手动更改版本更糟糕,并通过测试验证更改是否兼容。
  • 您可以考虑将数据保存为更易于更改的格式。也就是说,使用JSON/XML,你可以在不破坏以前版本的情况下添加字段。

一些版本控制系统可以使用关键字扩展机制。您可以使用它在签入或签出期间将更改/序列号/修订号(或其他名称)放入文件中。

TFS示例:关键字替换/扩展签入策略

在我的脑海中,要么创建一个transform-on-build T4,它构建一个.cs/类型名称的类/字典来散列/时间戳,要么标记该属性并钩子到MSBuild的BeforeBuild事件,在编译之前用类似的散列/lastmodified替换它。

编辑:好的,这里有几个非常粗糙的例子。

T4——在项目(.tt)中创建一个文本模板并粘贴以下

<#@ template hostspecific="true" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
namespace ClassLibrary1
{
    public class Version
    {
        <#  var project = new FileInfo(Host.ResolvePath("ClassLibrary1.csproj"));
            WriteLine("// " + project.FullName);
            var files = project.Directory.GetFileSystemInfos("*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var name = Path.GetFileNameWithoutExtension(file.Name);
                if (name == "Version")
                    continue; #>
               public const long <#= name #> = <#= file.LastWriteTime.Ticks #>;
        <#  } #>
    }
}

你现在有一个类,你可以在比较中使用的版本。名称常量。

MSBuild——编辑你的.csproj并在末尾添加以下内容。

<UsingTask TaskName="Version" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)'Microsoft.Build.Tasks.v4.0.dll">
  <ParameterGroup>
    <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
  </ParameterGroup>
  <Task>
    <Using Namespace="System.IO" />
    <Using Namespace="System.Text.RegularExpressions" />
    <Code Type="Fragment" Language="cs"><![CDATA[
          var regex = new Regex(@"Version = ('d+);//(-?'d+)");
          foreach (var file in Files)
          {
              var source = File.ReadAllText(file.ItemSpec);
              var match = regex.Match(source);
              if (!match.Success) continue;
              var hash = regex.Replace(source, string.Empty).GetHashCode();
              if (int.Parse(match.Groups[2].Value) == hash) continue;
              source = regex.Replace(source, string.Format("Version = {0};//{1}", int.Parse(match.Groups[1].Value) + 1, hash));
              File.WriteAllText(file.ItemSpec, source);
          }
      ]]></Code>
  </Task>
</UsingTask>
<Target Name="BeforeBuild">
  <Version Files="@(Compile)" />
</Target>

然后将public const int Version = 0;//0添加到您的类中。在编译之前,MSBuild将获取文件的哈希值,如果之前的计数器不匹配,则更新计数器。

在这些例子中有一个可以做得更好的例子,但希望它们能说明你可以采取的方向。也许有一个更好的方法,这是我在用Mono哈希IL后突然想到的两个想法。塞西尔,我觉得这个问题很有趣。如果您确实走任何一条路线,我建议阅读T4及其Host以及如何在构建上强制再生,或MSBuild和扩展事件,自定义和内联任务,甚至可能进入EnvDTE, CodeDOM, Microsoft.Build.Evaluation名称空间等,而不仅仅是搜索。cs文件和正则化。