我正在编写一个程序,允许加载特定的托管.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中执行。
答案 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
}
}
根本不是类型安全的,并且需要在呼叫者方面进行强制转换。不过,我不知道是否有更好的解决方案,如果你不愿意暴露你的内部类型。