C # Генератор случайных кодовых полей для объекта - PullRequest
3 голосов
/ 29 октября 2009

У меня есть объект со следующими свойствами


GID
ID
код
Имя

Некоторые клиенты не хотят вводить Код, поэтому первоначальный план заключался в том, чтобы ввести идентификатор в код, но базовый объект формы отличается, поэтому я как бы облажался ...

Мой план состоял в том, чтобы поместить #### - #### совершенно случайные значения в код, как я могу генерировать что-то подобное, скажем, что-то типа последовательного генератора Windows 7, но не будет ли это накладных расходов, что вы будете делать в этом случай.

Ответы [ 3 ]

3 голосов
/ 29 октября 2009

Хотите случайное значение или уникальное значение?

случайный! = Уникальный .

Помните, что случайное просто указывает вероятность , а не , генерирующую то же значение, или вероятность генерации того же значения снова . С течением времени вероятность генерирования предыдущего значения возрастает - становится почти наверняка. Что вам нужно?

Лично я рекомендую просто использовать Guid с некоторым контекстом [см. самый простой раздел ниже]. Я также предоставил некоторые другие предложения, чтобы у вас были варианты, в зависимости от вашей ситуации.


простой

Если код представляет собой неограниченную строку [то есть может иметь любую длину], то самым легким разборчивым средством создания уникального кода будет

OrmObject ormObject= new OrmObject ();
string code = string.
    Format ("{0} [{1}]", ormObject.Name, Guid.NewGuid ()).
    Trim ();
// generates something like
// "My Product [DA9190E1-7FC6-49d6-9EA5-589BBE6E005E]"

Вы можете заменить ormObject.Name на любую различимую строку. Обычно я использую typeof (objectInstance.GetType ()).Name, но это будет работать только в том случае, если OrmObject является базовым классом, если это конкретный класс, используемый для всего , все они будут заканчиваться похожими тегами. Смысл в том, чтобы добавить некоторый пользовательский контекст, такой, как, например, в статье wtf , на которую ссылается @Yuriy Faktorovich, - пользователям нужно что-то для чтения.


случайные

Я ответил день или два назад о генерации случайных чисел. Не столько генерация чисел, сколько создание простой гибкой структуры вокруг генератора для улучшения качества кода и данных, это должно помочь упростить ваш источник .

Если вы прочитаете это, вы можете легко написать метод расширения, скажем

public static class IRandomExtensions
{
    public static CodeType GetCode (this IRandom random)
    {
        // 1. get as many random bytes as required
        // 2. transform bytes into a 'Code'
        // 3. bob's your uncle
        ...
    }
}

    // elsewhere in code
    ...
    OrmObject ormObject = new OrmObject ();
    ormObject.Code = random.GetCode ();
    ...

Чтобы создать значение, я бы предложил реализовать интерфейс IRandom с реализацией System.Security.Cryptography.RNGCryptoServiceProvider. Упомянутая реализация будет генерировать буфер из X случайных байтов и выдавать столько, сколько потребуется, регенерируя поток при исчерпании.

Более того - я не знаю, почему я продолжаю писать, я думаю, эта проблема действительно очень интересная! - если CodeType является строкой и вы хотите что-то читаемое, вы можете просто взять указанные случайные байты и превратить их в «кажущуюся» читаемую строку с помощью преобразования Base64

public static class IRandomExtensions
{
    // assuming 'CodeType' is in fact a string
    public static string GetCode (this IRandom random)
    {
        // 1. get as many random bytes as required
        byte[] randomBytes; // fill from random
        // 2. transform bytes into a 'Code'
        string randomBase64String = 
            System.Convert.ToBase64String (randomBytes).Trim ("=");
        // 3. bob's your uncle
        ...
    }
}

Помните

случайный! = Уникальный .

Ваши значения будут повторяться. В конце концов.


уникальный

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

  1. Должны ли все Code значения быть уникальными? [если нет, ты слишком стараешься]
  2. Какой тип Code? [если строка произвольной длины, используйте полный Guid]
  3. Это распределенное приложение? [если нет, используйте значение БД, как предложено @LBushkin выше]
  4. Если это распределенное приложение, могут ли клиентские приложения генерировать и отправлять экземпляры этих объектов? [если это так, то вам нужен глобальный уникальный идентификатор, и снова Guids - верная ставка]

Я уверен, что у вас есть больше ограничений, но это пример того типа запроса, который вам нужно выполнить, когда вы сталкиваетесь с проблемой, подобной вашей. Из этих вопросов вы придумаете ряд ограничений. Эти ограничения проинформируют ваш дизайн.

Надеюсь, это поможет:)

Кстати, вы получите более качественные решения, если опубликуете более подробную информацию [то есть ограничения] по вашей проблеме. Опять же, какой тип Code, есть ли ограничения по длине? Ограничения формата? Символьные ограничения?

Arg, последнее редактирование, я клянусь . Если вы в конечном итоге используете Guids, вы можете скрыть это или даже «сжать» их представление, кодируя их в base64 - аналогично преобразованию base64, приведенному выше для случайных чисел.

public static class GuidExtensions
{
    public static string ToBase64String (this Guid id)
    {
        return System.Convert.
            ToBase64String (id.ToByteArray ()).
            Trim ("=");
    }
}

В отличие от усечения, преобразование base64 является , а не преобразованием с потерями. Конечно, приведенная выше урезка является проигрышной в контексте полного расширения base64 - но = - это просто дополнение, дополнительная информация, представленная на преобразование, а не часть исходных данных Guid. Если вы хотите перейти назад к Guid из этого преобразованного значения base64, то вам придется повторно дополнять строку base64, пока ее длина не будет кратна 4 - не спрашивайте, просто посмотрите base64 если вам интересно :)

1 голос
/ 29 октября 2009

Вы можете создать Guid используя:

Guid.NewGuid().ToString();

Это даст вам что-то вроде:

788E94A0-C492-11DE-BFD4-FCE355D89593

0 голосов
/ 29 октября 2009

Используйте столбец Autonumber или Sequencer из вашей базы данных, чтобы сгенерировать уникальный кодовый номер. Почти все современные базы данных поддерживают автоматически генерируемые числа в той или иной форме. Посмотрите, что поддерживает ваша база данных.

Значения Autonumber / Sequencer из БД гарантированно являются уникальными и относительно недорогими в приобретении. Если вы хотите избежать абсолютно последовательных чисел, назначенных кодам, вы можете дополнить и объединить несколько значений секвенсора вместе.

...