博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
A bit of reflection on C# reflection
阅读量:3976 次
发布时间:2019-05-24

本文共 5064 字,大约阅读时间需要 16 分钟。

C# reflection is supposed to fully or at least to a great extent cover all C# language constructs and features from an IL perspective. That's why I have been addicted to using it whenever possible or at least as a fall-back. However it does have some limitations and implications that we can never be too aware of.

What I've found or been told about includes,

- Performance concerns, reflection-based approach is almost always slower and requiring more runtime memory space than its non-reflection equivalent if any

- Can be incredibly harder to maintain and read; code is made significantly longer than normal

- Far more error-prone to code

- May become unusable as the code it works or depends on changes, even if it is such a slight change that most developers think shouldn't cause any problem. Considerable testing is needed when any of such changes are made.

- .NET reflection interface and implementation are subject to rapid change from version to version as well, which might affect the usability of existing code more than one has expected.

- Certain code protection or transformation approaches or processes such as obfuscation may render reflection unworkable all at once;

- Doesn't in all aspects look very elegant, symmetric from either an aesthetic point of view or a engineering one as far as the current state of reflection is concerned

- May differ from a normal approach in the context of execution, such as the context in which the assemblies are loaded.

- May be over-specific or less specific than expected so that types or other language elements retrieved are not what the user actually wanted or it is totally impossible to do it in the way she is trying and thinks would work.

The following is an example I recently came across in regards to what reflection can do but has to be done in a far less straightforward way,

The problem came with the difficulty of retrieving private members (like property, say) of an instance of a class.

In this case, I have a base class Project and a derived class ConcreteProject, where a variable called AtomicIdGenerator of long integer type is defined as a private member in the base. In one functional module of the solution where the persistence logic needs to be able to retrieve and modify any variables and entity that are required to be persisted, I did manage to get access to this private variable through reflection using BindingMode.NonPublic, which is attributed to the fact that C# reflection does enable us to do that.

abstract class Project{    [Persist]    private long AtomicIdGenerator { get; set; }    //...}class ConcreteProject : Project{    //...}

However the problem came when I tried to go through all the persistent entities in the OO model in order to create a complete copy of the persistent part of the whole model. I found most of the data was transferred fine, except for only a few points that I identified with a data persistence (database) comparison tool I made, with one of which being related to this particular property.

After a bit of investigation and discussion with my senior, I suddenly realised that it might be due to the way reflection treats private members in a class, especially when inheritance is involved. This is a very good example of this classic problem luckily provided by the only such variable in the entire solution we have built up so far.

The detailed explanation is reflection doesn't look at the accessibility of a class member the same way as we coders are used to, especially for those non-public ones such as protected, private and internal. Firstly they treat them on an IL level and from an IL perspective, which means they break down the concept of for instance 'private' into its real meaning which is being not accessible from outside of the class and specific (private) to this particular class only, which is pretty much a combination of 'protected' and 'confined in the class' with an 'and' logic applied to them. That's why one can't access it through reflection on the derived class which is what I get on the first occasion from an entity, which in this case an instance of B. To make it simple, a private member of a base class is, unlike a protected member of the base class, not a 'non-public' member of that class. So in order to do what I want I have to traverse the inheritance hierarchy of the instance to find out all the private members I need to deal with, and some ugly tricks need to be done that instead of relying on non-existent 'private' binding mode I may have to have a hash set or something to keep track of all the members I have dealt with and look for only those I haven't from a collection of members returned by the reflection call with an inevitably less restricted selection criterion say BindingMode.NonPublic among others.

What I wanted to mention in the end of this article is that the reason why I didn't get into this problem previously was simply because in preparing mapping for persistence I work with each specific type as it is, so there's no need to look into base classes in the hierarchy.

转载地址:http://mheki.baihongyu.com/

你可能感兴趣的文章
Windows下解决TerminateThread终止线程导致死锁问题
查看>>
linux下线程编程的注意到和推荐做法
查看>>
几个图论和复杂网络的程序库 —— BGL,QuickGraph,igraph和NetworkX
查看>>
odoo8 or openerp 通过xml id获取数据库id
查看>>
判断字符串是否是正确的IP格式的C语言函数
查看>>
C++学习顺序指导
查看>>
linux下擦除、写入flash的简单编程参考
查看>>
js在前端判断上传文件的大小
查看>>
C++学习书籍和顺序推荐
查看>>
C++学习书籍顺序推荐(二)----如何学好C++
查看>>
VC++多线程编程详解
查看>>
图结构入门
查看>>
创建图结构
查看>>
MFC实现类似qq的在屏幕右下角动画显示消息窗口
查看>>
MFC非模态对话框使用详解
查看>>
QE的本质
查看>>
安装交叉编译工具arm-linux-gcc命令未找到的问题
查看>>
C++字符串完全指引
查看>>
MFC改变鼠标形状的方法汇总
查看>>
交换机和路由器的数据包转发流程简述
查看>>