Отображение даты сборки

Я не знаком с FlowObservableCollection, но из того, что я смог найти, он, кажется, является подтипом ObservableCollection Microsoft Docs sup>.

Так как ObservableCollection сам по себе является подтипом Collection и, следовательно, реализует IEnumerable, у вас не должно возникнуть проблем с использованием его методов расширения , например, OrderBy.

Я могу видеть, что где-то люди используют:

list.OrderByDescending(x => DateTime.Parse(x)).ToList();

Моя ценность, по которой я хочу отсортировать, - это подзначение типа: mycollection.group.Myvalue

Вы знакомы с лямбда-выражениями , использованными в запросе LINQ вашего OrderByDescending() примера?

Если вы этого не сделаете, в [ 119] термин x относится к элементу в списке, и то, что вы указываете справа от стрелки =>, является вашим ключом для упорядочения.

Поэтому, если вы хотите упорядочить по другому значению, вы можете просто написать что-то вроде myCollection.OrderByDescending(x => x.MyProperty);. Обратите внимание, что вы можете использовать термины, отличные от x, если они одинаковы по обе стороны стрелки, например, myCollection.OrderByDescending(myElement => myElement.MyProperty);

Наконец, обратите внимание, что вызов myCollection.OrderByDescending() возвращает новый IEnumerable с элементами, найденными в myCollection, и не меняет сам myCollection.

Вы не можете разыграть IEnumerable на FlowObservableCollection. Поэтому, если вам нужен заказанный FlowObservableCollection, вам нужно создать новый экземпляр, используя заказанный IEnumerable в качестве входа.

В вашем случае это может выглядеть так:

var orderedElements = myCollection.OrderByDescending(x => x.MyProperty); 
var orderedCollection = new FlowObservableCollection(orderedElements);`

249
задан Luke Girvin 8 June 2016 в 00:38
поделиться

7 ответов

Jeff Atwood had a few things to say about this issue in Determining Build Date the hard way.

The most reliable method turns out to be retrieving the linker timestamp from the PE header embedded in the executable file -- some C# code (by Joe Spivey) for that from the comments to Jeff's article:

public static DateTime GetLinkerTime(this Assembly assembly, TimeZoneInfo target = null)
{
    var filePath = assembly.Location;
    const int c_PeHeaderOffset = 60;
    const int c_LinkerTimestampOffset = 8;

    var buffer = new byte[2048];

    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        stream.Read(buffer, 0, 2048);

    var offset = BitConverter.ToInt32(buffer, c_PeHeaderOffset);
    var secondsSince1970 = BitConverter.ToInt32(buffer, offset + c_LinkerTimestampOffset);
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    var linkTimeUtc = epoch.AddSeconds(secondsSince1970);

    var tz = target ?? TimeZoneInfo.Local;
    var localTime = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tz);

    return localTime;
}

Usage example:

var linkTimeLocal = Assembly.GetExecutingAssembly().GetLinkerTime();

UPDATE: The method was working for .Net Core 1.0, but stopped working after .Net Core 1.1 release(gives random years in 1900-2020 range)

354
ответ дан 23 November 2019 в 02:57
поделиться

это могло быть Assembly execAssembly = Assembly.GetExecutingAssembly(); var creationTime = new FileInfo(execAssembly.Location).CreationTime; // "2019-09-08T14:29:12.2286642-04:00"

0
ответ дан 23 November 2019 в 02:57
поделиться

Вы можете запустить дополнительный шаг в процессе сборки, который записывает метку даты в файл, который затем может быть отображен.

На вкладке свойств проекта посмотрите на вкладку событий сборки. Есть возможность выполнить команду до или после сборки.

1
ответ дан 23 November 2019 в 02:57
поделиться

I'm not sure, but maybe the Build Incrementer helps.

2
ответ дан 23 November 2019 в 02:57
поделиться

Вариант, который здесь не обсуждается, - это вставка ваших собственных данных в AssemblyInfo.cs, поле «AssemblyInformationalVersion» кажется подходящим - у нас есть пара проектов, в которых мы делали что-то подобное в качестве этапа сборки (однако я не совсем доволен тем, как это работает, поэтому не очень хочу воспроизводить то, что у нас есть).

На codeproject есть статья на эту тему: http: //www.codeproject .com / KB / dotnet / Customizing_csproj_files.aspx

9
ответ дан 23 November 2019 в 02:57
поделиться

Вы можете использовать событие после сборки проекта, чтобы записать текстовый файл в целевой каталог с текущей датой и временем. Затем вы можете прочитать значение во время выполнения. Это немного взломано, но должно работать.

2
ответ дан 23 November 2019 в 02:57
поделиться

The way

As pointed out by @c00000fd in the comments. Microsoft is changing this. And while many people don't use the latest version of their compiler I suspect this change makes this approach unquestionably bad. And while it's a fun exercise I would recommend people to simply embed a build date into their binary through any other means necessary if it's important to track the build date of the binary itself.

This can be done with some trivial code generation which probably is the first step in your build script already. That, and the fact that ALM/Build/DevOps tools help a lot with this and should be preferred to anything else.

I leave the rest of this answer here for historical purposes only.

The new way

I changed my mind about this, and currently use this trick to get the correct build date.

#region Gets the build date and time (by reading the COFF header)

// http://msdn.microsoft.com/en-us/library/ms680313

struct _IMAGE_FILE_HEADER
{
    public ushort Machine;
    public ushort NumberOfSections;
    public uint TimeDateStamp;
    public uint PointerToSymbolTable;
    public uint NumberOfSymbols;
    public ushort SizeOfOptionalHeader;
    public ushort Characteristics;
};

static DateTime GetBuildDateTime(Assembly assembly)
{
    var path = assembly.GetName().CodeBase;
    if (File.Exists(path))
    {
        var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)];
        using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            fileStream.Position = 0x3C;
            fileStream.Read(buffer, 0, 4);
            fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset
            fileStream.Read(buffer, 0, 4); // "PE\0\0"
            fileStream.Read(buffer, 0, buffer.Length);
        }
        var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        try
        {
            var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER));

            return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1) + new TimeSpan(coffHeader.TimeDateStamp * TimeSpan.TicksPerSecond));
        }
        finally
        {
            pinnedBuffer.Free();
        }
    }
    return new DateTime();
}

#endregion

The old way

Well, how do you generate build numbers? Visual Studio (or the C# compiler) actually provides automatic build and revision numbers if you change the AssemblyVersion attribute to e.g. 1.0.*

What will happen is that is that the build will be equal to the number of days since January 1, 2000 local time, and for revision to be equal to the number of seconds since midnight local time, divided by 2.

see Community Content, Automatic Build and Revision numbers

e.g. AssemblyInfo.cs

[assembly: AssemblyVersion("1.0.*")] // important: use wildcard for build and revision numbers!

SampleCode.cs

var version = Assembly.GetEntryAssembly().GetName().Version;
var buildDateTime = new DateTime(2000, 1, 1).Add(new TimeSpan(
TimeSpan.TicksPerDay * version.Build + // days since 1 January 2000
TimeSpan.TicksPerSecond * 2 * version.Revision)); // seconds since midnight, (multiply by 2 to get original)
87
ответ дан 23 November 2019 в 02:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: