【问题标题】:How "safe" are Anonymous Types and Reflection together?匿名类型和反射在一起有多“安全”?
【发布时间】:2009-01-06 21:48:37
【问题描述】:

我想这也可能被问到创建的类型名称附加到匿名类型多长时间。问题来了:

一个博客有这样的东西:

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 之类的 Session 中几乎可以工作吗? IE 的类型名称会特定于程序的每个实例吗?还是会比这更糟?什么时候该名称会被丢弃和覆盖?

【问题讨论】:

  • 非常皮条客。我无法回答你,但我受到启发将你的一些想法融入我自己的代码中。我使用网络,所以我不必担心会话或匿名类型名称。
  • 为什么不改用Dictionary&lt;Type, Dictionary&lt;String, PropertyInfo&gt;&gt;
  • 嗯...因为我知道你会建议它并希望你自我感觉良好?你买那个吗?
  • 我可以买那个。它有效,我对自己感觉良好。谢谢。

标签: c# reflection anonymous-types


【解决方案1】:

从来没有。该类型是在编译时生成的,您可以认为它在应用程序域的整个生命周期中都是不变且唯一的。

我质疑这个函数的价值。显而易见的第一个原因是因为您没有 String 类的 Format 方法的大部分功能(括号没有转义,括号中的值没有格式等)。

第二个是它基本上将格式字符串链接到传入的类型,因此它们不容易被换出。如果我有两个具有相同概念值但命名它的属性不同的类,我必须更改我的格式字符串以使用您的方法显示它,以补偿属性名称嵌入在格式字符串中的事实。

【讨论】:

  • 主要的想法是我可以绕过必须创建大量的东西并伴随它的 1,2,3,4。并不是说这是一个好主意,只是认为这可能是一个有趣的练习。
【解决方案2】:

匿名类型是在编译时生成的,因此只要不重新编译程序集,反射名称就应该是静态的。

有一个详细的帖子here 描述了这些名称,但我相信你所做的是安全的。

【讨论】:

    【解决方案3】:

    我有两件事要说,但这并不是真正的答案。

    首先,字典不一定要有字符串键;关键可能是实际类型。即它可能是Dictionary&lt;Type, Dictionary&lt;String, PropertyInfo&gt;&gt;。这会更快,因为您不必获取类型名称,并且更不容易出错 - 如果我向该方法发送两个具有相同名称但名称空间不同的非匿名类型怎么办?

    其次,您应该阅读 Phil Haack 最近关于此主题的 blog post。它包含此类方法的完整实现。

    【讨论】:

    • 我认为这就是我最初的想法的来源,但我想自己尝试一下,看看是否可以。老实说,到目前为止,这通过了支架测试,并且在第一次之后非常快。但是,是的,阅读整篇文章可能不会伤害我。
    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多