Как решить "Должен быть MarshalByRefObject" в хорошем, но множественном наследовании ампутационном языке, таком как С#?

Как решить "Должен быть MarshalByRefObject" в хорошем, но множественном наследовании ампутационном языке, таком как С#?

Проблема очень проста, в некоторых случаях вам просто нужно наследовать этот класс (требования к инфраструктуре). Здесь неважно, какие случаи. Итак, что вы будете делать, если вы уже унаследовали от какого-либо другого класса (требования к вашей модели домена)?

Btw хорошие фреймворки приложений, такие как spring.net, всегда убедитесь, что вам НЕ нужно наследовать этот класс независимо от того, какую инфраструктуру вам нужно применить к вашему классу.

Я хотел бы знать, что я получаю -3 голосов здесь?:)

Ответы

Ответ 1

В общем, вы хотите создать объект MarshalByRef, если собираетесь использовать его в контексте Remoting/WCF. Обычно это довольно-таки особый случай, когда это не боль.

Предположим, что у вас был общий тип, и вы хотели извлечь из него и специализироваться на нем, а затем удалять производный тип - теперь у вас есть проблема, поскольку для удаления объекта, который должен наследовать объект из MarshalByRefObject, и ваш оригинальный общий тип не сделал. Предположим, вы не можете изменить его, потому что вы выполняете двоичное наследование или потому, что оно само происходит из базового класса, который вы не можете изменить? Как указывает вопроситель, поскольку С# (и .NET вообще) не разрешает MI, вы не можете наследовать от обоих.

Короткий ответ заключается в том, что вы сокрушились. Вы либо изменяете общий тип на наследование из MarshalByRefObject (или заходите достаточно далеко вверх по цепочке, в которую вы можете вставить ее где-то в действие), или вы можете думать о том, чтобы сбрасывать объекты с прокси-объектами.

Например, вы можете создать контракт на интерфейс, который описывает ваш тип интерфейса, а затем построить прокси-тип, наследующий от MarshalByRefObject, который также реализует этот интерфейс по композиции и делегированию в экземпляр вашего типа (т.е. оболочку). Затем вы могли удалять экземпляр этого типа прокси, который бы создавал экземпляр вашего типа и выполнял работу, как ожидалось, но все возвращаемые типы из методов должны быть [Serializable].

public interface IMyType
{
    string SayHello();
    string BaseTypeMethodIWantToUse();
}

public class MyType : MyBaseType, IMyType
{
    public string SayHello()
    {
        return "Hello!";
    }
}

public class MyRemoteableType : MarshalByRefObject, IMyType
{
    private MyType _instance = new MyType();

    public string SayHello()
    {
        return _instance.SayHello();
    }

    public string BaseTypeMethodIWantToUse()
    {
        return _instance.BaseTypeMethodIWantToUse();
    }
}

Кажется, много работы. В конечном счете, если вы в этом сценарии, я бы предложил редизайн или переосмысление.

Ответ 2

Это зависит от того, как вам нужно это делать. Использование базового класса, который происходит из MarshalByRefObject, может это сделать. Агрегация может это сделать. Без более конкретного примера того, что вам нужно, трудно сказать, но это редкий случай, когда множественное наследование будет единственным решением проблемы.

Ответ 3

Вы не можете наследовать несколько классов. Таким образом, вам нужно либо (а) изменить иерархию наследования, чтобы база наследовала от нее, либо (б) написать свое приложение по-другому.

Без дополнительной информации о том, почему вам нужно наследовать от MarshalByRefObject или почему ваш базовый класс не делает (не может?), тогда трудно дать более конкретные рекомендации.

Но я бы сказал, что если у вас есть производный тип, который нуждается в различной семантике маршалинга к своей базе, тогда у вас, вероятно, есть архитектурная проблема.

Ответ 4

"Итак, что вы будете делать, если вы уже унаследовали от какого-либо другого класса (требования к вашей модели домена)?"

Можно ли создать базовый класс для части вашей модели домена, требующей наследования из MarshalByRefObject?

Ответ 5

У меня был успех с общим подходом. T не обязательно должен быть "MarshalByRefObject". Конечно, вам придется заменить "RemoteProcess" на объект, который вы используете для удаленного доступа. Затем вы можете получить доступ к вашему объекту, отличному от MarshalByRefObject, как RemotingHost.RemoteObject.

public class RemotingHost<T> : MarshalByRefObject where T: class
{
    RemoteProcess host;
    T remoteObject;
    public T RemoteObject { get { return remoteObject; } }

    public RemotingAdmin()
    {
        host = new RemoteProcess();
        remoteObject = (T)host.CreateObject(typeof(T));
    }
}