解決方法“ MarshalByRefObjectでなければなりません” C#のような適切な複数継承切断言語で?
-
10-07-2019 - |
質問
" MarshalByRefObjectである必要があります"の解決方法C#のような適切な複数継承の切断された言語ですか?
この問題は非常に単純です。いくつかのケースでは、このクラスから継承する必要があります(インフラストラクチャ要件)。 ここでは、実際には問題ではありません。 では、他のクラス(ドメインモデルの要件)から既に継承している場合はどうしますか?
spring.netなどの優れたアプリケーションフレームワークでは、クラスに適用する必要があるインフラストラクチャの種類に関係なく、このクラスから継承する必要がないことを常に確認します。
ここで-3票を得ているものを知りたいのですが?? :)
解決
一般的に、オブジェクトをRemoting / WCFコンテキストで使用する場合にのみ、オブジェクトMarshalByRefを作成します。これは通常、痛みではないという特別に十分なケースです。
一般的な型があり、それから派生して特殊化し、派生した型をリモートにしたい場合-オブジェクトがMarshalByRefObjectと元の一般的な型から継承される必要があるため、問題が発生しましたしなかった。バイナリ継承を行っているため、または変更できない基本クラスから派生しているため、変更できないとしますか?質問者が指摘するように、C#(および一般的に.NET)はMIを許可しないため、両方から継承することはできません。
簡単な答えは、あなたはちょっとおかしいということです。一般的な型をMarshalByRefObjectから継承するように変更する(または、チェーンを十分に効果的な場所に挿入できる)か、プロキシオブジェクトをいじることについて考えることができます。
たとえば、型のインターフェイスを記述するインターフェイスコントラクトを作成してから、MarshalByRefObjectを継承するプロキシ型を構築し、そのインターフェイスを構成および型のインスタンス(つまりラッパー)への委任によって実装することもできます。次に、そのプロキシ型のインスタンスをリモート化して、型をインスタンス化し、期待どおりに処理を実行できますが、メソッドからの戻り型はすべて[シリアル化可能]である必要があります。
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();
}
}
しかし、多くの作業のようです。最終的に、このシナリオにいる場合は、再設計または再考することをお勧めします。
他のヒント
それを達成する方法によって異なります。 MarshalByRefObjectから派生した基本クラスを使用することで可能になります。集約がそれを行うかもしれません。必要なもののより具体的な例がなければ、言うのは難しいですが、多重継承が問題の唯一の解決策になることはまれです。
複数のクラスから継承することはできません。そのため、(a)ベースが継承するように継承階層を変更するか、(b)アプリケーションを異なる方法で記述する必要があります。
なぜに関する詳細な情報がなければ、 MarshalByRefObject
から継承する必要があるか、基本クラスが継承しない(できない?)理由は具体的なアドバイスを与えるのが難しいからです。
しかし、ベースに対して異なるマーシャリングセマンティクスを必要とする派生型がある場合、おそらくどこかにアーキテクチャ上の問題があると思います。
"では、他のクラス(ドメインモデルの要件)から既に継承している場合はどうしますか?"
MarshalByRefObjectからの継承を必要とするドメインモデルの基本クラスを作成できますか?
一般的なアプローチで成功しました。 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));
}
}