Reflection MethodAccessException

时间:2014-12-18 12:07:41

标签: c# silverlight reflection

我在Silverlight中有一个简单的代码:

public void temp()
{
    try
    {                
        WriteableBitmap obj = new WriteableBitmap(10, 10);

        //PropertyInfo pr = obb.GetType().GetProperty("Pixels");
        Type type = obj.GetType();
        Type typeofType = type.GetType();

        MethodInfo getPropMethod = typeofType.GetMethod("GetProperty", new Type[] { typeof(string) }); //get method info
        PropertyInfo pix1 = type.GetProperty("Pixels"); // first call - no exceptions
        PropertyInfo pix2 = (PropertyInfo)getPropMethod.Invoke(type, new object[] { "Pixels" }); // second call - MethodAccessException
    }
    catch (Exception ex)
    {
    }
}

方法GetProperty的第一次调用已成功执行,并且不会抛出任何异常。 但第二次调用 - methodInfo.Invoke抛出MethodAccessException - 为什么会发生这种情况?

异常和Stacktrace:

MethodAccessException: Attempt by security transparent method 'System.Type.GetProperty(System.String)' to access security critical method 'SilverlightApplication3.MainPage.temp()' failed.

in System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags)
in System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags)
in System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
in System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
in System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
in SilverlightApplication3.MainPage.temp()

2 个答案:

答案 0 :(得分:1)

Silverlight中的反射仅限于在编译时可用的内容,也许是在第一次调用某些内容发生更改并且无法执行反射之后,您在调用函数时满足条件的第一次。

  

在Silverlight中,您无法使用反射来访问私有类型和   成员。如果类型或成员的访问级别会阻止您   从静态编译的代码中访问它,您无法访问它   动态地使用反射。

请参阅here了解文档

答案 1 :(得分:0)

我认为这是Silverlight / CoreCLR模型中强大的安全限制的结果。

我认为反映方法(或其底层实现)将被视为SecurityCritical。你现在的反射代码似乎仍然满足这一点,但我认为这是一个特别不允许的特殊情况(可能是由于安全问题)。使用委托和编译时引用的类似代码在Silverlight中工作正常,包括调用该委托的所有各种方法:

var getPropMethodDelegate = new Func<string, PropertyInfo>(obj.GetType().GetType().GetProperty);
getPropMethodDelegate("Pixels");
getPropMethodDelegate.Invoke("Pixels");
getPropMethodDelegate.DynamicInvoke("Pixels");

但检索相同功能并通过反射调用它的行为不起作用。我怀疑这是一个特例。我无法找到特定的文档来指明这一点(也许它是here所写内容的含义),但错误消息似乎表明使用了{{1调用安全关键方法使其被视为&#34;安全透明&#34;。

我不知道是否有特定的解决方法,而且我不知道您的具体案例。我建议也许避免使用反射来获取MethodInfo反射方法的MethodInfo个对象,并简单地使用普通委托。如果必须让它动态确定要使用的System.Type反射方法,那么可以放入一个基于传入方法名称的包装器,而不是返回编译时委托引用。例如:

System.Type

或者在这一点上,直接做到这一点:

if (reflectionType == "GetProperty")
{
    var getPropertyInfoDelegate = new Func<string, PropertyInfo>(obj.GetType().GetType().GetProperty);
    PropertyInfo propertyInfo = getPropertyInfoDelegate(propertyName);
}

您可以做更多工作来简化此操作(例如,将例程放在字典中以便快速查找),但对于Silverlight / CoreCLR上下文,我不知道如何解决这个问题。