.NET远程处理异常:权限被拒绝:无法远程调用非公共或静态方法

时间:2010-03-23 04:00:52

标签: c# .net exception remoting

我正在编写一个程序,允许加载特定的托管.DLL文件并使用它。由于我希望能够卸载.DLL文件,我正在创建两个AppDomain - 一个用于app本身,另一个用于当前加载的.DLL。

由于加载的.DLL中的大多数对象都没有很好地序列化,我正在创建一个MarshalByRefObject包装类,它将对象本身保存在自己的AppDomain中,并向主应用程序公开一些反射函数应用程序域。

但是当我尝试在远程对象上调用某个方法时,我遇到了异常:

  

权限被拒绝:无法远程调用非公共或静态方法。

这很奇怪,因为我根本没有使用任何非公共或静态方法。从本质上讲,我所拥有的是:

class RemoteObjectWrapper: MarshalByRefObject
{
    private Type SourceType;
    private object Source;

    public RemoteObjectWrapper(object source)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        this.Source = source;
        this.SourceType = source.GetType();
    }
    public T WrapValue<T>(object value)
    {
        if ( value == null )
            return default(T);
        var TType = typeof(T);
        if (TType == typeof(RemoteObjectWrapper))
            value = new RemoteObjectWrapper(value);
        return (T)value;
    }
    public T InvokeMethod<T>(string methodName, params object[] args)
    {
        return WrapValue<T>(SourceType.InvokeMember(methodName,
            System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Instance |
            System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, this.Source, args));

    }
}

当我尝试时,我得到了例外:

var c = SomeInstanceOfRemoteObjectWrapper.InvokeMethod<RemoteObjectWrapper>("somePublicMethod", "some string parameter");

这里发生了什么?据我所知,InvokeMethod方法甚至没有被执行,当我尝试运行它时抛出异常。

已添加:为了澄清 - SomeInstanceOfRemoteObjectWrapper是在.DLL的AppDomain中构建的,然后返回到我的主AppDomain,InvokeMethod<T>()从我的主AppDomain调用(和{期望它在.DLL的AppDomain中执行。

2 个答案:

答案 0 :(得分:5)

即使方法InvokeMethod<T>是公开的,它也包含在内部类中。 C#中没有修饰符使其成为内部修饰符。因此InvokeMethod<T>的有效可见性是内部的,您将获得异常。公开RemoteObjectWrapper应解决此问题。

答案 1 :(得分:3)

我有完全相同的问题。如果你是一个对象,如:

class MyClass : MarshalByRefObject
{
  public T Foo<T>() where T : MarshalByRefObject {
    // stuff
  }
}

使用内部类型T调用MyClass.Foo可以正常工作,但只要您的MyClass对象不是远程的。我想这是因为你不一定假设你正在进行呼叫的地方有任何访问权限。但是,当你无法公开你使用的类型时,这是非常尴尬的。你有时可以通过包装或替换Foo来解决它:

class MyClass : MarshalByRefObject
{
  public object Foo(Type t) {
    // stuff
  }
}

根本不是类型安全的,并且需要在呼叫者方面进行强制转换。不过,我不知道是否有更好的解决方案,如果你不愿意暴露你的内部类型。