Is reflection a violation of the encapsulation principle?

Well, let's say we have a class defined as

public class TestClass { private string MyPrivateProperty { get; set; } // This is for testing purposes public string GetMyProperty() { return MyPrivateProperty; } } 

then we will try:

 TestClass t = new TestClass { MyPrivateProperty = "test" }; 

Compilation TestClass.MyPrivateProperty is inaccessible due to its protection level with TestClass.MyPrivateProperty is inaccessible due to its protection level , as expected.

Try

 TestClass t = new TestClass(); t.MyPrivateProperty = "test"; 

and compilation failed with the same message.

Everything is good so far, we expected this.

But then write:

 PropertyInfo aProp = t.GetType().GetProperty( "MyPrivateProperty", BindingFlags.NonPublic | BindingFlags.Instance); // This works: aProp.SetValue(t, "test", null); // Check Console.WriteLine(t.GetMyProperty()); 

and here we are, we managed to change the private field.

Is it not normal to be able to change any internal state of an object using reflection only?

Edit:

Thanks for answers. For those who say “you don’t need to use it”: what about the class designer, it seems he can no longer accept internal security?

+8
reflection c # oop
Nov 25 '09 at 10:34
source share
9 answers

Reflection violates encapsulation principles by providing access to private fields and methods, but this is not the first or only way to bypass encapsulation; it can be argued that serialization provides all the internal data of a class, information that is usually private.

It’s important to understand that encapsulation is just a technique that simplifies design if consumers agree to use the API you defined. If someone decides to bypass your API using reflection or any other technique, they no longer have confidence that your object will behave the way you designed it. If someone assigns null to a private field, they should be prepared to catch a NullReferenceException the next time they try to use your class!

In my experience, programming is all statements and assumptions. The language asserts restrictions (classes, interfaces, enumerations) that make creating isolated behavior much easier to do based on the assumption that the consumer agrees not to violate these boundaries.

It is a fair statement to do this, which makes the sharing and subjugation approach to software development easier than any technique before it.

+13
Nov 25 '09 at 11:28
source share

Reflection is a tool . You can use it to break encapsulation when it gives you more than it takes away.

Reflection has a certain “pain” (or cost — in performance, readability, code reliability) associated with it, so you won’t use it for a common problem. It’s just easier to follow object-oriented principles for common problems, which is one of the goals of the language, commonly called the pit of success ,

On the other hand, there are some problems that would not be solvable without this mechanism, for example. working with runtime generation types (although it will be much simpler starting with .NET 4.0 with its DLR and "dynamic" variables in C # 4.0).

+8
Nov 25 '09 at 10:37
source share

I suppose you could say that. You can also say that the CodeDom, Reflection Emit, and Expression Tree APIs break encapsulation, letting you write code on the fly. These are just tools provided by .NET. You do not have to use them.

Remember that you must (a) work in full trust and (b) explicitly specify BindingFlags.NonPublic in order to access your personal data. This should be enough to ensure security.

+3
Nov 25 '09 at 10:40
source share

You are right that reflection can be contrasted with any number of good design principles, but it can also be an important building block that you can use to support good design principles - for example, software that can be extended with plugins, invert controls, etc.

If you are concerned that it is an ability that should be discouraged, you might have a point. But it is not so convenient to use as true language functions, so it is easier to do something right.

If you think reflection should be impossible, you are dreaming!

In C ++, there is no reflection as such. But there is a basic “object model” that computer code created by the compiler uses to access the structure of objects (and virtual functions). That way, a C ++ programmer can break encapsulation in the same way.

 class RealClass { private: int m_secret; }; class FakeClass { public: int m_notSecret; }; 

We can take a pointer to an object of type RealClass and simply pass it to FakeClass and access the "private" element.

Any limited system must be implemented on top of a more flexible system, so you can always get around it. If reflection was not presented as a BCL function, someone could add it using a library using unsafe code.

In some languages, there are ways to encapsulate data so that it is not possible to receive data other than certain specific methods. But you can always be fooled if you can find a way to get away from your tongue. An extreme example would be scope variables in JavaScript:

 (function() { var x = 5; myGetter = function() { return x; }; mySetter = function(v) { x = v; }; })(); 

After that, the global namespace contains two functions: myGetter and mySetter , which are the only way to access the value of x . Javascript has no reflexive ability to get x any other way. But it must run in some kind of host interpreter (for example, in the browser), and therefore, of course, there is some terrible way to manipulate x . A memory error in the plugin could have done this by accident!

+3
Nov 25 '09 at 10:58
source share

It can be said that reflection also destroys inheritance and polymorphism. When instead of supplying each type of object with its own version of the overloaded method, you have a single method that checks the type of the object at runtime and switches to a specific behavior for each.

Reflection is a good tool, though. Sometimes you need to create an instance of an object using a private constructor, because this is the optimal course of action, and you cannot change the implementation of the class (closed library, I can no longer contact the author). Or do you want to perform some auxiliary operation on different objects in one place. Or perhaps you want to register for certain types. This is a situation where reflection helps without causing any harm.

+2
Nov 25 '09 at 10:37
source share

This part of the functionality provided by Reflection, but not, I would say, made the best use of it.

He works only under full confidence.

+2
Nov 25 '09 at 10:38
source share

No, that’s not normal.
This is what allows you to make a reflection, in some situation, what you have done can be useful, in many others, that just makes your code a time bomb.

Reflection is a tool; it can be used or abused.


Regarding the question after your editing: the answer is simply no. An API designer could do his best with a lot of effort to expose a clean interface and see that its API is being overused by reflection.

An engineer can simulate an ideal washing machine that is reliably protected, does not shock you with electricity and so on, but if you hit with a hammer until you see the cables, no one will blame the engineer if you get hit: D

+2
Nov 25 '09 at 10:42
source share

The encapsulation principle is followed by your API, but reflection gives you the ability to get around the API.

Anyone who uses reflection knows that he is using your API incorrectly!

+2
Nov 25 '09 at 10:45
source share

Reflection can help you keep your code clean. For example. when you use sleep mode, you can directly bind private variables to DB values, and you do not need to write unnecessary tuning methods that you do not need. From this perspective, reflection can help you maintain encapsulation.

+1
Nov 25 '09 at 10:54
source share



All Articles