From time to time, every developer comes upon some code that should be public but isn't. I'm not talking about decompiling your competitors application but just a simple case of an API that someone marked as internal or a protected field on a sealed class. Oversight, really, that means a simple bug fix that should require just a single method call becomes some clunky workaround because you just can't do it properly. Clearly, a case of object encapsulation gone wrong.
.NET has the reflection mechanism that allows one to sidestep those restrictions - however, reflection is not simple to use and is simply slow. It's meant more as a way of examining your objects once and then acting on this information, not for querying over and over each time you need to call a method. Doing this repeatedly will obviously kill the performance of your application.
Wouldn't it be great to be able to just flip a switch and be able to write myObjectInstace.CallPrivateMethod();?
With Cognifide ExposedObject you can do just that! Using the magic of .NET 4.0 and
dynamic keyword to allow you to expose and access hidden fields, methods and properties as if they were public by generating appropriate wrapper code in runtime. It is backed by the Dynamic Language Runtime caching mechanism, which allows it to perform at minimal overhead. It's also available on NuGet, so you can add it to your project easily. A simple usage example for your delight:
// create an Exposed instance from a ClassWithHiddenMethods instance dynamic exposed = Exposed.From(new ClassWithHiddenMethods()); // calling a private method string password = exposed.GeneratePassword(8); // reading a private field int privateFieldValue = exposed.internalCount; // setting a private field exposed.internalCount = privateFieldValue * 2; // reading a protected property char protectedPropertyValue = exposed.InternalData;
Accessing private field on a hidden type:
// get the Type via reflection Type hiddenClass = Type.GetType("TestSubjects.HiddenClass, TestSubjects"); // call the parameterless constructor of a hidden type dynamic exposed = Exposed.New(hiddenClass); string password = exposed.password;
Calling an internal static method from type handle:
dynamic exposedType = Exposed.From(typeof(ClassWithInternalStaticMethod)); decimal convertValue = exposedType.ConvertValue(8);
If you are interested in the code underneath that makes this possible, be sure to hit the github repository at https://github.com/Cognifide/ExposedObject - there's documentation, an interesting reading list and plenty of unit tests if you need more usage samples. Remember to use ExposedObject responsibly - it makes breaking the visibility contract easy and inexpensive, but should not be abused. If you find that you are using it to expose your own code, you probably should revisit your design to make it more accessible. And finally: please get back to us with any interesting use cases and comments!
We're always looking for new faces to join the Cognifide family. Take a look at our available jobs.