A few months ago I created a framework to work with objects in a more transactional way. The basic idea is that you can edit properties on an object and call AcceptChanges() to accept the changes and RejectChanges() to reject the changes. Also I implemented all of the required interfaces for rich databinding in windows forms and WPF.
This weekend I decided that it would be kinda cool to move the framework over to silverlight, since you can perform rich databinding there too. However this didn’t go without a few hickups and nasty problems. One of them being reflection.
The perils of code access security
One of the very first problems I noticed was the fact that Activator.CreateInstance() works way different. It cannot be used to invoke private constructors on types. This is one of the features of my framework that makes it possible to initialize the object state for the first time.
The first bummer with the constructor I can live with. However, another trick I build was to invoke private methods as some form of callbacks for retrieving, inserting, updating and deleting data from the backend inside my entities. This allows the entity to set the value of “readonly” fields that you otherwise cannot set when using for example a data factory design-pattern.
Why did they do this?
Microsoft has decided to enforce the rules for private, internal and protected methods, even if you are using reflection. They are doing this because silverlight is used in the browser which is inheritly unsecure. To prevent nasty viruses from getting a grip on silverlight or your system, microsoft has decided to prevent access to private methods. I think this is great from a security standpoint, but it does make the challenge a whole lot bigger for me.
There is a solution
While scanning the Microsoft website for a little more information I discovered that it is possible to invoke private methods using reflection. Instead of using MethodInfo.Invoke you need to create a delegate to the method and invoke that delegate.
More information
- Information on security with reflection: http://msdn.microsoft.com/en-us/library/stfy7tfc(VS.95).aspx
- How to get around the limitation of invoking private methods: http://msdn.microsoft.com/en-us/library/ms228976(VS.95).aspx
3 comments
I tried DynamicInvoke and that didn’t work either.
Here is my attempt:
public class Container
{
private void Handler()
{
Debugger.Break();
}
}
public App()
{
Container c = new Container();
var handler = c.GetType().GetMethod(“Handler”, BindingFlags.Instance | BindingFlags.NonPublic);
//throws exeption
handler.Invoke(c, new object[] { });
//throws exception
var d = Delegate.CreateDelegate(typeof(Action), c, “Handler”);
d.DynamicInvoke();
}
Shimmy
Also, the workaround for private methods is only for static, instance methods are not supported. Any workarounds? Can I grant my apps with some extra trusts for that?
Shimmy
There isn’t a known workaround for instance methods. Other than making them public.
You can’t grant yourself extra trusts, because that would break the Silverlight security model.
Check out this article by MS on how the security model of Silverlight works: http://msdn.microsoft.com/en-us/library/dd470128(v=VS.95).aspx
Willem Meints