Исключение удаленного взаимодействия .NET: Отказано в доступе: невозможно удаленно вызывать непубличные или статические методы - PullRequest
4 голосов
/ 23 марта 2010

Я пишу программу, которая позволит загружать определенный управляемый файл .DLL и играть с ним. Поскольку я хочу выгрузить файл .DLL, я создаю два домена приложений - один для самого приложения, другой для загруженного в данный момент .DLL.

Поскольку большинство объектов в загруженном .DLL не сериализуются должным образом, я создаю класс-оболочку MarshalByRefObject, который будет хранить сам объект в своем собственном AppDomain и предоставлять некоторые функции отражения для основного 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 даже не выполняется, возникает исключение, когда я пытаюсь его запустить.

Добавлено: Для пояснения - в домене приложений .DLL создается SomeInstanceOfRemoteObjectWrapper, а затем возвращается в мой основной домен приложений. InvokeMethod<T>() вызывается из моего основного домена приложений (и я ожидаю, что он будет выполнен домен приложений .DLL).

Ответы [ 2 ]

5 голосов
/ 23 марта 2010

Даже метод InvokeMethod<T> является открытым, он содержится во внутреннем классе. Никакой модификатор в C # не делает его внутренним. Следовательно, эффективная видимость InvokeMethod<T> является внутренней, и вы получаете исключение. Обнародование RemoteObjectWrapper должно решить эту проблему.

3 голосов
/ 13 августа 2010

У меня точно такая же проблема. Если вы такой объект, как:

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

Вызовы MyClass.Foo с внутренним типом T работают нормально, но только до тех пор, пока ваш объект MyClass не является удаленным. Я полагаю, это потому, что вы не можете обязательно предполагать, что место, в которое вы звоните, имеет какой-либо доступ к T. Однако очень неудобно, когда вы не можете сделать тип, который вы используете, публичным. Иногда вы можете обойти это, обернув или заменив Foo на:

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

Который вообще не безопасен для типов и требует приведения на стороне вызывающего. Однако я не знаю, есть ли лучшее решение, если вы не хотите раскрывать свой внутренний тип.

...