如何解决“Must be MarshalByRefObject”问题 使用 C# 等良好但多重继承截断的语言?

发布于 2024-07-09 01:04:07 字数 274 浏览 6 评论 0原文

如何在 C# 等良好但多继承截断语言中解决“Must be MarshalByRefObject”问题?

问题很简单,在某些情况下你只需要继承这个类(基础设施要求)。 在这里,哪种情况并不重要。 那么,如果您已经从其他类继承(您的领域模型要求),您该怎么办?

顺便说一句,好的应用程序框架,例如 spring.net 总是确保您不必从此类继承,无论您需要将哪种基础结构应用于您的类。

我想知道我为什么在这里得到-3票? :)

How to solve "Must be MarshalByRefObject" in a good but multiple-inheritance amputated language like C#?

The problem is very simple, in several cases you just have to inherit from this class (infrastructure requirements).
It does not matter here really, which cases.
So, what do you do if you've already inherited from some other class (your domain model requirements)?

Btw good application frameworks, like spring.net always make sure you DON'T have to inherit from this class no matter what kind of infrastructure you need to apply to your class.

I would like to know what am I getting -3 votes here for?? :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦里泪两行 2024-07-16 01:04:07

一般来说,如果要在远程处理/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();
    }
}

不过,看起来工作量很大。 最终,如果您处于这种情况,我建议重新设计或重新思考。

In general you only want to make an object MarshalByRef if you're going to use it in a Remoting / WCF context. This is usually a special-enough case that it's not a pain.

Suppose you had a general type, and you wanted to derive from it and specialise it, and then remote the derived type - now you have a problem, because to be remoted an object must inherit from MarshalByRefObject, and your original general type didn't. Suppose you can't change it because you're doing binary inheritance, or because it itself derives from a base class you can't change? As the questioner points out, since C# (and .NET in general) doesn't allow MI, you can't inherit from both.

The short answer is that you're sort-of screwed. You either change the general type to inhert from MarshalByRefObject (or go far enough up the chain that you can insert it somewhere effective), or else you can think about mucking about with proxy objects.

You could for example create an interface contract that describes your type's interface, and then build a proxy type inheriting from MarshalByRefObject that also implements that interface by composition and delegation to an instance of your type (ie a wrapper). You could then remote an instance of that proxy type which would instantiate your type and do the work as expected - but all return types from methods have to be [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();
    }
}

Seems like a lot of work, though. Ultimately if you're in this scenario I'd suggest a redesign or a rethink.

清秋悲枫 2024-07-16 01:04:07

这取决于您需要如何实现它。 使用从 MarshalByRefObject 派生的基类可以做到这一点。 聚合可能会做到这一点。 如果没有更具体的示例来说明您需要什么,很难说,但在极少数情况下,多重继承将是问题的唯一解决方案。

It depends on how you need to get at it. Using a base class that derives from MarshalByRefObject might do it. Aggregation might do it. Without a more concrete example of what you need it's hard to say, but it's a rare case that multiple inheritance would be the only solution to a problem.

北方的韩爷 2024-07-16 01:04:07

您不能从多个类继承。 因此,您要么需要 (a) 更改您的继承层次结构,以便基础继承它,要么 (b) 以不同的方式编写您的应用程序。

如果没有更多关于为什么您需要从 MarshalByRefObject 继承或为什么您的基类不继承(不能?)的信息,那么很难给出任何更具体的建议。

但我想说,如果您有一个派生类型,需要对其基础使用不同的封送语义,那么您可能在某个地方遇到了体系结构问题。

You can't inherit from multiple classes. So you either need to (a) change your inheritance hierarchy so the base inherits from it, or (b) write your application differently.

Without more information about why you need to inherit from MarshalByRefObject or why your base class does not (cannot?) then it's hard to give any more concrete advice.

But I'd say if you have a derived type that needs different marshaling semantics to its base, then you've probably got an architectural issue somewhere.

独自←快乐 2024-07-16 01:04:07

“那么,如果您已经从其他类继承(您的领域模型要求),您该怎么办?”

您能否为需要从 MarshalByRefObject 继承的域模型部分创建一个基类?

"So, what do you do if you've already inherited from some other class (your domain model requirements)?"

Can you create a base class for the piece of your domain model that requires inheritance from MarshalByRefObject?

追风人 2024-07-16 01:04:07

我通过通用方法取得了成功。 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));
    }
}

I had success with a generic approach. T doesn't have to be "MarshalByRefObject". Of course you'll have to replace "RemoteProcess" with the object you use for remoting. Then you can access your non-MarshalByRefObject as 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));
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文