2009-12-13 50 views
12

我正在阅读和学习C#中的反射。知道它在日常工作中如何能够帮助我很好,所以我希望有比我更多经验的人告诉我样品或想法,我们可以使用它来实现什么样的事情,或者我们如何减少代码量我们写的。反思。我们可以使用它来实现什么?

谢谢。

+1

相关问题:http://stackoverflow.com/questions/1859902/in-3-minutes-what-is-reflection – 2009-12-13 21:02:08

+1

相关是的,但我个人认为这个问题是相当无益的。积分是相反的推导是微积分,但我敢打赌,告诉你,即使你知道什么是推导,也教你几乎没有任何东西。 :D – 2009-12-13 23:08:08

回答

10

最近,我用它来添加自定义属性在我的枚举字段:

public enum ShapeName 
{ 
    // Lines 
    [ShapeDescription(ShapeType.Line, "Horizontal Scroll Distance", "The horizontal distance to scroll the browser in order to center the game.")] 
    HorizontalScrollBar, 
    [ShapeDescription(ShapeType.Line, "Vertical Scroll Distance", "The vertical distance to scroll the browser in order to center the game.")] 
    VerticalScrollBar, 
} 

使用反射来获取字段:

public static ShapeDescriptionAttribute GetShapeDescription(this ShapeName shapeName) 
    { 
     Type type = shapeName.GetType(); 
     FieldInfo fieldInfo = type.GetField(shapeName.ToString()); 
     ShapeDescriptionAttribute[] attribs = fieldInfo.GetCustomAttributes(typeof(ShapeDescriptionAttribute), false) as ShapeDescriptionAttribute[]; 

     return (attribs != null && attribs.Length > 0) ? attribs[0] : new ShapeDescriptionAttribute(ShapeType.NotSet, shapeName.ToString()); 
    } 

属性类:

[AttributeUsage(AttributeTargets.Field)] 
public class ShapeDescriptionAttribute: Attribute 
{ 
    #region Constructor 
    public ShapeDescriptionAttribute(ShapeType shapeType, string name) : this(shapeType, name, name) { } 

    public ShapeDescriptionAttribute(ShapeType shapeType, string name, string description) 
    { 
     Description = description; 
     Name = name; 
     Type = shapeType; 
    } 
    #endregion 

    #region Public Properties 
    public string Description { get; protected set; } 

    public string Name { get; protected set; } 

    public ShapeType Type { get; protected set; } 
    #endregion 
} 
9

一般来说,Reflection允许您访问关于对象的元数据。将反射与其他技术结合使用,可以使您的程序更具活力。例如,您可以加载一个DLL并确定它是否包含接口的实现。你可以用它来发现在运行时支持功能的dll。使用可以使用它来扩展应用程序而无需重新编译,也无需重新启动它。

智能感知在Visual Studio中使用反射来给你,你正在使用的对象的信息。

注意,使用反射是有代价的。反射对象可能会很慢。但是,如果你需要它反射是一个非常有用的工具。

+1

您可以通过多种方式减轻这些成本;基于反射的代码可以像常规代码一样快。 – 2009-12-13 22:33:07

0

我只用在生产代码反射一次。在这种情况下,我不得不做出调整 - 到目前为止 - 在启动例程中已经标准化地使用了一种特定的类方法(抱歉,不要更具体 - 它是前一段时间,细节是朦胧)。解决问题的唯一方法是引入不同版本的方法,并在运行时检查各种标准/代码条件等,以确定我应该调用哪种方法。这是一段非常紧凑的代码,它提供了一个解决问题的简单方法,否则这些问题将是一个难以解决的问题。

0

这里有一些事情我已经使用了反思,将是非常困难或不可能没有它:

  • StringTemplate模板引擎我的C#端口。反射用于检索动态对象的属性。
  • 一个CLI JIT编译器托管代码编写。

Managed Extensibility Framework(一个新的.NET库)使用反射来:

  • 找到并组成部分,包括施加进口。
  • 它避免了装载组件的执行,直到需要的内容。
2

其中一种用途:您可以制作一个插件体系结构,您可以在其中指定配置文件中使用的类的名称。使用反射,您可以使用此字符串并创建请求的对象的实例。如果该对象实现了一个已知的接口,那么你可以通过普通的(非反射)代码来使用它。

1

我已经使用了反射来让我更加灵活地满足不断变化的需求。也就是说,客户在数据库中放置数据库表的位置不断变化。我所做的只是让对象自己检查其字段并在对象本身内调用这些字段的对象构造函数。那么,如果应该在别的地方找到一张桌子?点击,粘贴,完成。

这并没有在最终的生产中出现,请注意,但在迭代阶段中删除了一些我需要更改的样板。

1

我使用反射来帮助翻译控件,如标签和按钮在我们的表单上。使用反射我会浏览表单上的所有控件,并将控件名称,文本和标题写入XML文件。在XML中翻译控件标题和文​​本后,将该XML中找到的每个控件的标题和文本设置为已翻译的值,从而读回该文件。
我们的表格需要翻译成几种不同的语言,使用反射帮助我们节省了大量时间。

-1

我使用Red Gate .Net Reflector来更好地理解.Net框架本身的机制。曾经想知道为什么某个特定的框架对象会以它的方式工作,或者为什么某些工作不按照您认为的方式工作?

有时候文档可能有点破旧,但至少可以说,但通过使用反射和Redgate的工具,您可以在框架代码中嗅探到,以便更好地理解它的方式/原因/内容。

通过使用反射的“MS外部人员”在CLR代码中发现了一些以上的错误。

+1

我需要检查,但我不确定反射镜如何使用反射;我的印象是它直接读取并解析IL,而不是使用反射API。 – 2009-12-13 22:32:11

3

对于没有任何需要知道调用者的库代码来说,它是非常宝贵的 - 就像泛型一样,但对数据的访问更丰富。例子:

  • 奥姆斯(物化等)
  • 串行/解串
  • 对象克隆/深复制
  • UI /绑定代码(严格这是ComponentModel,但你可以混合使用这两种 - 为例如,HyperDescriptor)

您当然应该尝试尽量减少反射的数量,但您可以通过缓存代表fr来降低成本OM Delegate.CreateDelegate/Expression/DynamicMethod

1

在VS属性窗口是基于反射 - 如果你让一个用户控件,你可以从PropertyGrid瞬间(其还可以,如果你想使用控制)修改它的属性。当然,你可以添加属性来增强它的显示方式(通过反射来访问)。

我也用它来实现一个自定义的二进制序列化类。

这里我有一个类,我使用反射序列化/反序列化它 - 并提供其他UI信息的属性。

[TypeConverter(typeof(IndexedExpandableObjectConverter))] 
[BinarySerializeable] 
public sealed class Socket 
{ 
    #region Fields (7)  

    [SerializedPosition(0)] 
    Byte _mode = 1; 

    ... 

    [SerializedPositionAttribute(4)] 
    UInt16 _localPort; 

    ... 

#区域属性(5)

[DisplayName("Listning Port")] 
    [Description("The port which the socket will listen for connections on")] 
    [DisplayIndex (0)] 
    public UInt16 LocalPort 
    { 
     get { return _localPort; } 
     set { _localPort = value; } 
    } 

    ... 

,系列化的功能 - 你可以看到,它只是需要一个对象和字节顺序(字节序)你想要的。其他一切都是由反思决定的。默认SerializationProvider在对象内的字段上使用SerializedPosition属性(专用或不专用)。

public static Byte[] Serialize(Object obj, ByteOrder streamOrder) 
{ 

    var provider = GetProvider(obj); 

    if (provider.CanSerialize(obj.GetType())) 
     return provider.Serialize(obj, streamOrder); 

    throw new ArgumentException(obj.GetType() + " is non-serialisable by the specified provider '" + provider.GetType().FullName + "'."); 
} 


private static IBinarySerializatoinProvider GetProvider(Object obj) 
{ 

    var providerAttrib = Reflector.GetAttribute<BinarySerializationProviderAttribute>(obj); 

    if (providerAttrib != null) 
     return CreateProvider(providerAttrib.ProviderType); 

    return CreateProvider(typeof(SerializationProvider)); 
} 
0

我想这一个“独立”的应用程序,其中每一个对象,你使用在编译时被称为,你不使用反射了。

但是,当编写应该在编译时使用未知对象(完全 - 您可能了解接口或基类)的库或框架代码时,反射对于使用这些对象来说可能是非常宝贵的。

1

这是方法来执行基于一个枚举或魔术字符串方法...


    public enum ReflectionTestMethods 
    { 
     MethodA, 
     MethodB, 
     MethodC 
    } 
    public class ReflectionTest 
    { 

     public void Execute(ReflectionTestMethods method) 
     { 
      MethodInfo methodInfo = GetType().GetMethod(method.ToString() 
       , BindingFlags.Instance | BindingFlags.NonPublic); 
      if (methodInfo == null) throw new NotImplementedException(method.ToString()); 
      methodInfo.Invoke(this, null); 
     } 

     private void MethodA() 
     { 
      Debug.Print("MethodA"); 
     } 

     private void MethodB() 
     { 
      Debug.Print("MethodB"); 
     } 

     private void MethodC() 
     { 
      Debug.Print("MethodC"); 
     } 
    } 

但是,这也许是一个更好的解决方案...


    public class ActionTest 
    { 
     private readonly Dictionary _actions = new Dictionary(); 

     public ActionTest() 
     { 
      _actions.Add(ReflectionTestMethods.MethodA.ToString(), new Action(MethodA)); 
      _actions.Add(ReflectionTestMethods.MethodB.ToString(), new Action(MethodB)); 
      _actions.Add(ReflectionTestMethods.MethodC.ToString(), new Action(MethodC)); 
     } 

     public void Execute(ReflectionTestMethods method) 
     { 
      if (!_actions.ContainsKey(method.ToString())) 
       throw new NotImplementedException(method.ToString()); 
      _actions[method.ToString()](); 
     } 

     private void MethodA() 
     { 
      Debug.Print("MethodA"); 
     } 

     private void MethodB() 
     { 
      Debug.Print("MethodB"); 
     } 
     private void MethodC() 
     { 
      Debug.Print("MethodC"); 
     } 
    } 
0

我用它来:

  • 依赖注入
  • 变通办法微软缺乏动机添加的东西,如“协变/逆变通用”与“新的()与参数约束”
  • 面向方面编程(在一定程度上,主要是我用PostSharp)
0

思考是很好的“后期绑定”解决方案,您不希望将物理参考连接到您的项目,而是稍后“连接”它。这样,如果参考不存在并且不重要,则不会丢失缺少参考的错误。你会得到一个你可以处理的控制错误。

相关问题