Насколько «безопасны» анонимные типы и рефлексия вместе? - PullRequest
4 голосов
/ 07 января 2009

Полагаю, здесь также можно спросить, как долго имя созданного типа прикрепляется к анонимному типу. Вот проблема:

В блоге было что-то вроде этого:

var anonymousMagic = new {test.UserName};

lblShowText.Text = lblShowText
                     .Text
                     .Format("{UserName}", test);

Как список пожеланий и несколько способов сделать это. Будучи скучающим и предприимчивым, я занялся созданием метода расширения строки, который мог бы справиться с этим:

var anonymousMagic = new {test.UserName, test.UserID};

lblShowText.Text = "{UserName} is user number {UserID}"
                     .FormatAdvanced(anonymousMagic);

С мыслью, что я получу информацию о свойствах от анонимного типа и сопоставлю ее со строками в скобках. Теперь с информацией о свойствах приходит отражение, поэтому я хотел бы сохранить информацию о свойствах при первом обращении к типу, чтобы мне не пришлось получать ее снова. Итак, я сделал что-то вроде этого:

    public static String FormatAdvanced(this String stringToFormat, Object source)
    {

        Dictionary<String, PropertyInfo> info;
        Type test; 
        String typeName;
        //
        currentType = source.GetType();
        typeName = currentType.Name;
        //
        //info list is a static list for the class holding this method
        if (infoList == null)
        {
            infoList = new Dictionary<String, Dictionary<String, PropertyInfo>>();
        }
        //
        if (infoList.ContainsKey(typeName))
        {
            info = infoList[typeName];
        }
        else
        {
            info = test.GetProperties()
                       .ToDictionary(item => item.Name);
            infoList.Add(typeName, info);
        }  
        //
        foreach (var propertyInfoPair in info)
        {
            String currentKey;
            String replacement;

            replacement = propertyInfoPair.Value.GetValue(source, null).ToString();
            currentKey = propertyInfoPair.Key;

            if (stringToFormat.Contains("{" + currentKey + "}"))
            {
                stringToFormat = stringToFormat
                                 .Replace("{" + currentKey + "}", replacement);
            }
        }  
        //
        return stringToFormat;
    }

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

Если несколько человек одновременно используют этот метод, будет ли он работать в режиме Session, например, в режиме fastsion; IE названия типов будут специфичны для каждого экземпляра программы? Или это будет еще хуже? В какой момент это имя забрасывается и перезаписывается?

Ответы [ 3 ]

3 голосов
/ 07 января 2009

Анонимные типы создаются во время компиляции, поэтому имена отражений должны быть статичными, если вы не перекомпилируете сборку.

Здесь есть подробный пост здесь , в котором описаны имена, но я верю, что вы делаете безопасно.

3 голосов
/ 07 января 2009

Это никогда не происходит. Тип генерируется во время компиляции, и вы можете считать его постоянным и уникальным в течение всего жизненного цикла домена приложения.

Я ставлю под сомнение значение этой функции. Первая очевидная причина заключается в том, что у вас недостаточно функциональности метода Format в классе String (нет перехода в квадратные скобки, нет форматирования значений в квадратных скобках и т. Д. И т. Д.).

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

1 голос
/ 07 января 2009

Мне нужно сказать две вещи, но на самом деле это не ответ.

Прежде всего, в словаре не должно быть строкового ключа; ключ может быть фактическим типом. то есть это может быть Dictionary<Type, Dictionary<String, PropertyInfo>>. Это было бы быстрее, потому что вам не нужно получать имя типа и меньше подвержено ошибкам - что если я отправлю этому методу два неанонимных типа с одинаковым именем, но разными пространствами имен?

Во-вторых, вы должны прочитать недавнее сообщение Фила Хаака в блоге на эту тему. Содержит полную реализацию такого метода.

...