1

したがって、私はクラスの大きなコレクションを持っており、クラスが更新されると、既存の保存されたデータに対して update メソッドを実行する必要があります。現在、私は次のようなものを使用しています:

public const decimal LatestVersion = 0.0121201313m;
private decimal LastVersion;

//...

if (Abilities.LastVersion != Abilities.LatestVersion)
{
    //...

そして、クラスを更新するたびに、LatestVersion 番号を手動で更新します...また、更新が必要なすべてのクラスでこのメソッドを繰り返す必要があります。うまく機能しますが、バージョン番号を更新することを忘れないでください。

私が考えているのはDateTime、クラスが変更された場合などに、LatestVersion が自動的に現在のバージョンに更新されるようにすることです (おそらくデバッグ コマンドを使用)...しかし、それは可能ではないと思います。

クラスレベルで自動実装バージョン管理システムをセットアップする方法について、他にアイデアはありますか?

4

3 に答える 3

2

バージョンのクラスファイルで、空白以外のコンテンツのある種のハッシュを使用できます。クラスごとに 2 つのファイルが必要です。ソースが 1 つ、ビルド時に生成されるファイルが 1 つですが、変更を加えるとバージョンが変更されることが保証されます。念のため、ハッシュに日付を追加する必要があるかもしれません。

 // 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 を使用すると、以前のバージョンを壊すことなくフィールドを追加できます。
于 2013-01-22T17:22:10.383 に答える
2

一部のバージョン管理システムでは、キーワード拡張メカニズムを使用できます。これを使用して、チェックインまたはチェックアウト中に変更/シリアル/リビジョン番号 (またはそれが呼ばれるもの) をファイルに入れることができます。

TFS の例:キーワード置換/拡張チェックイン ポリシー

于 2013-01-22T17:43:27.873 に答える
1

私の頭の上から、.cs/type 名のクラス/ディクショナリを構築してハッシュ/タイムスタンプにするトランスフォーム オン ビルドT4を作成するか、そのプロパティをトークン化し、MSBuild のBeforeBuildイベントにフックして、コンパイル前に同様のものに置き換えます。ハッシュ/最終変更。

編集:わかりましたので、ここに非常に大雑把な例をいくつか示します。

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 #>;
        <#  } #>
    }
}

これで、Version.ClassName 定数を介した比較で使用できるクラスができました。

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.Cecil で IL をハッシュした後に頭に浮かんだ最初の 2 つのアイデアです。この質問は非常に興味深いものでした。いずれかのルートに進む場合は、T4 とそのビルド時の再生成を強制する方法、または MSBuild とイベントの拡張、カスタム タスクとインライン タスクを読むことをお勧めHostEnvDTEます。正規表現。CodeDOMMicrosoft.Build.Evaluation

于 2013-01-22T18:59:56.733 に答える