19

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?? :)

Paul Kapustin
  • 3,297
  • 5
  • 35
  • 45
  • I think you might need to provide more context about what the actual problem is here... – Greg Beech Nov 24 '08 at 01:49
  • I suspect your -3 votes is for the (now edited) quip about a "multiple-inheritance amputated language". Not everyone agrees that multiple-inheritance is a good idea. – Mitch Wheat Nov 24 '08 at 02:10
  • 3
    Plus a lot of people probably haven't come across MarshalByRefObject and are unaware of why you'd have this problem and without a more compelling explanation (which you've provided now) were downvoting it to get rid of it. – Neil Hewitt Nov 24 '08 at 02:12
  • 2
    It's true that MI is not always a good idea, but neither is goto. But it's undeniable that at times each is the best solution. It's sometimes very frustrating that C++, Perl, & Eiffel are about the only major languages that offer MI. This is one of those cases. The OP has a valid point. – P Daddy Nov 24 '08 at 02:23
  • In the case of MarshalByRefObject, because C# has no MI, they really should have made it an interface. – P Daddy Nov 24 '08 at 02:24
  • I'm not a big believer in multiple inheritance, but geeze, that's my opinion--it's sad that disagreement (if that's the case) led to a downvote. – rp. Nov 24 '08 at 02:25
  • I down-voted it because I didn't get your question (before edit). I have been programming in .Net since 2001, so if I don't get it then a lot of other people won't get it. I judged this to be a poor question. With your edit I canceled my down-vote. It would seem my down-vote did some good. – Jason Jackson Nov 24 '08 at 02:27
  • @P Daddy - It is an object not an interface for performance reasons; MBRO prevents method inlining, and making it an object rules out vastly more polymorphic cases where methods could or could not be this type of object vs if it was an interface, specifically due to lack of multiple inheritance. – Greg Beech Nov 24 '08 at 02:30
  • @Jason Jackson: smiles. Now I almost speculated votes on this question...:) – Paul Kapustin Nov 24 '08 at 02:43
  • @Greg Beech: if you paste your comment about why MBRO is a class, as an answer and expand it very little bit (i didn't get 100%) - you will get at least one up vote :))) Hmm...now I am probably going to get downvoted again for corruption :)... – Paul Kapustin Nov 24 '08 at 02:45

5 Answers5

19

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.

Neil Hewitt
  • 2,518
  • 18
  • 24
  • alas, sometimes you are stuck with a 3rd party api full of unmarshalable types :( – Daren Thomas Sep 02 '09 at 13:01
  • Is there any disadvantage of inheriting from MarshalByRefObject? Suppose I have a base class that's used in many places, would this cause any problems with performance or anything else? – Mas Aug 23 '12 at 07:58
  • As a base class it does little or nothing - it just makes the compiler / jitter treat the class specially and makes it proxyable (see http://stackoverflow.com/questions/2720703/is-marshalbyrefobject-special). Given that WCF has made Remoting obsolete, I wouldn't bother with MarshalByRefObject at all anymore. – Neil Hewitt Aug 24 '12 at 10:25
  • @NeilHewitt would you not consider it even in AppDomain situations? It's rather handy to be able to use classes in separate app domains together through the proxying mechanism... Or at least I think so. :P – Alex Oct 08 '13 at 07:24
  • @Alex - across app domain boundaries is essentially remoting anyway. But I take your point. I rarely have to do that sort of stuff these days. Back in the 1.1 days I used Remoting a lot because I needed distributed logic on the systems I was building. – Neil Hewitt Oct 14 '13 at 11:55
1

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.

ctacke
  • 66,480
  • 18
  • 94
  • 155
1

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.

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
  • 1
    The phrase "multiple-inheritance amputated language" acknowledges that the asker understands you can't inherit from multiple classes. – Aaron Palmer Nov 24 '08 at 02:28
  • @Aaron Palmer - that's why I first down voted Greg, however undid that when he added some more info which was actually useful...so now I voted him up :) – Paul Kapustin Nov 24 '08 at 02:35
  • 1
    Actually saying "language" does not fully acknowledge that - it is not the language that prohibits it, it is the .NET Framework, which is a different thing. So I felt it was worth clarifying that it is not possible to have multiple inheritance at all in .NET, not just in C#. – Greg Beech Nov 24 '08 at 02:40
  • @Greg Beech: well, probably, both...:) – Paul Kapustin Nov 24 '08 at 11:48
0

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));
    }
}
Joe
  • 2,496
  • 1
  • 22
  • 30
0

"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?

Aaron Palmer
  • 8,912
  • 9
  • 48
  • 77