1

I'm facing a problem that I need to construct one object from multiple types and return to the front end, here is what I want(In C#).

The shape that front end wants is like this

{
...
"props" : // this is the place I need to fill-up.
...
}

For the controller, it's a custom response.

        public IActionResult Index()
        {
            return JohnDoe.Render();
        }

Behind the scenes, Render is going to get some data from two places.

        public object Foo()
        {
            return string, int, IEnumerable, instance, etc;
        }

        public object Bar()
        {
            return string, int, IEnumerable, instance, etc;
        }

I know the return statement is not valid, what I mean is that those are all the possibilities.

And here is eventually what I want.

        public object Combine()
        {
            var foo = Foo();
            var bar = Bar();

            return foo + bar;
        }

Again the return statement is not valid, I want to have a final object that contains both of them. It can be Dictionary<string, object> or anonymous object new {}, or something else does not matter as long as one object has both of them.

Obviously what I have here is not possible to achieve it. Here are the two options I came up with.

  1. Just use a wrapper to wrap them, Here is what I do.
        public object Combine()
        {
            var foo = Foo();
            var bar = Bar();

            return new { foo, bar };
        }

I know I can have a Type rather than an anonymous object, the thing is that this will introduce two keys foo and bar, which I do not want to if possible.

  1. Make the foo and bar only return instance. NO string, int, Array, IEnumerable etc. If I do it in this way, things get a little bit easier. All I need to do is looping through the properties getting the values and map to either new {} or Dictionary<string, object>. This way I do not need to introduce new keys.

Update : so basically I want to avoid introducing new keys if I can, as I just want to return the original without a wrapper. That's why I came up with option 2, only instance is allowed. Let me know your thoughts, please.

Andy Song
  • 4,404
  • 1
  • 11
  • 29
  • 1
    This sounds like an X-Y problem. You have a problem X and you think that if you can do Y then you can solve that problem, and so you've come here to ask about Y and that's just confusing for us. How about you tell us what X actually is? What it is you're actually trying to do? – Enigmativity Nov 16 '19 at 01:55
  • @Enigmativity hahhah, you are absolutely right. however, this is the core of the problem though. – Andy Song Nov 16 '19 at 01:59
  • Yes, but your problem as stated is confusing and abstract. If you tell us what you are actually trying to do then we might be able to give a good answer. – Enigmativity Nov 16 '19 at 02:01
  • @Enigmativity I think you are right, I will update the question soon,. – Andy Song Nov 16 '19 at 02:06
  • @Enigmativity sorry, I did not make my question clear before, now I've updated the question, let me know if it's understandable. thanks – Andy Song Nov 16 '19 at 02:36
  • Just have one of your classes inherit the other one and you end up with a class with all properties combined in a single object – Jonathan Alfaro Nov 16 '19 at 02:37
  • Not sure I fully understand the question, but maybe this is the kind of thing you're looking to do? https://stackoverflow.com/questions/5130367/is-there-an-easy-way-to-merge-c-sharp-anonymous-objects – jlmt Nov 16 '19 at 02:37
  • You want to wrap 2 classes (or objects) into 1 single object, yet you don't want to create a containing class (object), nor do you want to return an anonymous object.C# isn't javascript, you can't just say `classA` + `classB` and expect `classAB` containing the properties of both classes. This is not how the language is designed. My answer still holds true. Create a viewmodel containing 1) Foo & Bar. Or 2) all the properties of Foo and all the properties of Bar. – Dennis VW Nov 16 '19 at 02:46
  • Json.Net have a merge method. `var foo = JObject.FromObject(Foo()); foo.Merge(JObject.FromObject(Bar())); var json = foo.ToString()`. But only work with object. Not primitives. Need some wrapper for it. – Kalten Nov 16 '19 at 16:38

3 Answers3

0

How about option 3)

  • create a class that acts as a wrapper for Foo and Bar called FooBar ?
public class FooBar
{
    public Foo Foo { get; set; }
    public Bar Bar { get; set; }
}

Why?

C# is an object-oriented programming language. And it's based on the concept of wrapping pieces of data, and behavior related to that data, into special bundles, called objects, which you construct from a 'blueprint' called a class.

Dennis VW
  • 2,977
  • 1
  • 15
  • 36
  • I think it is very similar to option 1. the only difference is that this one is type `FooBar`, option 1 is an anonymous object. I am not sure I like it. – Andy Song Nov 16 '19 at 01:57
  • sorry, I did not make my question clear before, now I've updated the question, let me know if it's understandable. thanks – Andy Song Nov 16 '19 at 02:23
0

You can use a Tuple:

    public Tuple<Foo, Bar> Combine()
    {
        var foo = Foo();
        var bar = Bar();

        return Tuple.Create(foo, bar);
    }

Or a ValueTuple:

    public (Foo, Bar) Combine()
    {
        var foo = Foo();
        var bar = Bar();

        return (foo, bar);
    }

Also with named fields:

    public (Foo foo, Bar bar) Combine()
    {
        var foo = Foo();
        var bar = Bar();

        return (foo, bar);
    }

Or, as Dennis1679 suggest, make a custom type.

Theraot
  • 31,890
  • 5
  • 57
  • 86
  • sorry, I did not make my question clear before, now I've updated the question, let me know if it's understandable. thanks – Andy Song Nov 16 '19 at 02:23
  • @AndySong I suppose out parameters won't help you either. Will returning an array of objects do? I do not know what causes to new keys what not. – Theraot Nov 16 '19 at 02:41
  • The thing is that when I return IEnumerable, I have to assign some magic keys. maybe like the index of the list. yes, so the question is really when I return array, I do know what for the key. – Andy Song Nov 16 '19 at 04:36
0

I think this is what you are asking

public sealed class FooBar : Foo, Bar
{

}

Unfortunately this is not possible in C#. But in essence this is what you are doing. You can do the following:

public sealed class FooBar: IFoo, IBar
{
    public FooBar(IFoo foo, IBar bar)
    {
        ///Assign its members
    }

    ///Implement its members
}
Thomas Heijtink
  • 427
  • 5
  • 7