Okay, so, I've got this code-

List<Post> list = new List<Post>();

            foreach(XElement post in posts)
            {
                var postType = post.Descendants();
                
                var type = (string)post.Attribute("type");

                Post item;

                if (type == "regular")
                {
                        item = new RegularPost();

                        item.title = (string)postType.ElementAt(0);
                        item.body = (string)postType.ElementAt(1);
                }
                if (type == "quote")
                {
                        item = new Quote();

                        item.source = (string)postType.ElementAt(1);
                        item.text = (string)postType.ElementAt(0);
                }

                if (type == "photo")
                {
                        item = new Photo();

                        item.caption = (string)postType.ElementAt(0);
                        var photoUrl = post.Descendants("photo-url");
                        foreach (var photoUrlSpecific in photoUrl)
                        {
                            var photoSize = (string)photoUrlSpecific.Attribute("max-width");
                            switch (photoSize)
                            {
                                case "500":
                                    item.url.width500 = (string)photoUrlSpecific;
                                    break;

                                case "400":
                                    item.url.width400 = (string)photoUrlSpecific;
                                    break;

                                case "250":
                                    item.url.width250 = (string)photoUrlSpecific;
                                    break;

                                case "100":
                                    item.url.width100 = (string)photoUrlSpecific;
                                    break;

                                case "75":
                                    item.url.width75 = (string)photoUrlSpecific;
                                    break;
                            }
                        }
                }

                item.date = (string)post.Attribute("date");
                item.id = (int)post.Attribute("id");

                list.Add(item);

Post is an abstract class whereas others are the classes that extend from it.

I've made sure that the methods exists and there are no typos but everytime I try compiling the program, it gives an error-

"Error 1 'Tumblarity.Post' does not contain a definition for 'title' and no extension method 'title' accepting a first argument of type 'Tumblarity.Post' could be found (are you missing a using directive or an assembly reference?)"

Is there any way to declare a single variable which can change its type depending upon the type of post? It should also be accessible so as to be added to a list.

Thanks in advance!

Recommended Answers

All 18 Replies

Is there any way to declare a single variable which can change its type depending upon the type of post? It should also be accessible so as to be added to a list.

A reference of type object can be set to any type. Then, you can determine type with typeof(string) or typeof(int) or typeof(Post) etc. .

I tried using Object item; to declare the var. It still gives the same error.

What line number of the original code gave you that error you said in the beginning?

What line number of the original code gave you that error you said in the beginning?

Its that line which has the child class specific field. The one with item.title and all the others with child specific fields.

Its that line which has the child class specific field. The one with item.title and all the others with child specific fields.

OK, so item.title in this code segment?:

if (type == "regular")
                {
                        item = new RegularPost();
 
                        item.title = (string)postType.ElementAt(0);
                        item.body = (string)postType.ElementAt(1);
                }

What is the definition of: Tumblarity.Post , which I assume is the object being returned by method RegularPost() ?

And, if you really want fast results, zip up your project and attach it so I can build it and reproduce the error quickly...

Tumblarity.Post is an abstract class. Here is the code-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using System.IO;
using System.Xml;

namespace Tumblarity
{
    public abstract class Post
    {
        public String urlWithSlug;
        public PostType type;
        public String date;
        public int id;

        public abstract PostType GetPostType();
        
    }

    public enum PostType
    {
        Regular = 0, Photo = 1, Quote = 2, Link = 3, Chat = 4, Audio = 5, Video = 6
    }

    public class Photo : Post
    {
        public String caption;
        public PhotoUrl url;

        public override PostType GetPostType()
        {
            return PostType.Photo;
        }

    }

    public struct PhotoUrl
    {
        public String width75;
        public String width100;
        public String width250;
        public String width400;
        public String width500;
    }

    public class RegularPost : Post
    {
        public String title;
        public String body;

        public override PostType GetPostType()
        {
            return PostType.Regular;
        }

    }

    public class Quote : Post
    {
        public String text;
        public String source;

        public override PostType GetPostType()
        {
            return PostType.Quote;
        }

    }

    class PostClass
    {
        public static List<Post> getPosts()
        {
            CurlClass curl = new CurlClass("http://xxxxxxxxx.tumblr.com/api/read");
            curl.sendRequest();

            MemoryStream memstream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(curl.xml));
            XDocument doc = XDocument.Load(XmlReader.Create(memstream));

            var posts = from post in doc.Descendants("post")
                        select post;

            List<Post> list = new List<Post>();

            foreach(XElement post in posts)
            {
                var postType = post.Descendants();
                
                var type = (string)post.Attribute("type");

                RegularPost post = new RegularPost();

                Object item;

                if (type == "regular")
                {
                        item = new RegularPost();

                        item.title = (string)postType.ElementAt(0);
                        item.body = (string)postType.ElementAt(1);
                }
                if (type == "quote")
                {
                        item = new Quote();

                        item.source = (string)postType.ElementAt(1);
                        item.text = (string)postType.ElementAt(0);
                }

                if (type == "photo")
                {
                        item = new Photo();

                        item.caption = (string)postType.ElementAt(0);
                        var photoUrl = post.Descendants("photo-url");
                        foreach (var photoUrlSpecific in photoUrl)
                        {
                            var photoSize = (string)photoUrlSpecific.Attribute("max-width");
                            switch (photoSize)
                            {
                                case "500":
                                    item.url.width500 = (string)photoUrlSpecific;
                                    break;

                                case "400":
                                    item.url.width400 = (string)photoUrlSpecific;
                                    break;

                                case "250":
                                    item.url.width250 = (string)photoUrlSpecific;
                                    break;

                                case "100":
                                    item.url.width100 = (string)photoUrlSpecific;
                                    break;

                                case "75":
                                    item.url.width75 = (string)photoUrlSpecific;
                                    break;
                            }
                        }
                }

                item.date = (string)post.Attribute("date");
                item.id = (int)post.Attribute("id");

                list.Add(item);
                
            }

            return list;
        }
    }
}

You have declared item Post item; to be abstract class reference, which does not contain an object called "title". Set your derived class specific objects like:

if (type == "regular")
            {
                RegularPost regularPost = new RegularPost(); // specific stuff
                item = regularPost; // reference to common stuff...

                regularPost.title = (string)postType.ElementAt(0);
                regularPost.body = (string)postType.ElementAt(1);

Then, "item" can still set the abstract objects that are common. Repeat this for the other derived objects.

I have tried using your method but then it does not allow me to access the child-class specific properties after returning the list.

You haven't provided nearly enough code for that project to compile. Can you upload the entire solution? I get 20+ build errors.

I have tried using your method but then it does not allow me to access the child-class specific properties after returning the list.

I don't know what you mean by "after returning the list". Here is an example of how you need to access the derived Post class (specific child-class) members, and then you can access the common base class members at the end as you were already doing. Nevermind that I stripped out all of the code not needed for demonstrating this concept.

string type = "regular"; // using to demonstrate given functionality
            
            // Declare object reference to access common base stuff from Post
            // Declaring outside of specific Post derived classes below so we
            // can access the common base information later...
            Post item;

            if (type == "regular")
            {
                RegularPost regPost = new RegularPost();
                item = regPost; // allow item object to access the base class members...

                // you can set title from RegularPost object because it is defined there,...
                regPost.title = "some text";

                // but NOT from the abstract class because that is not where it is defined
                //item.title = "some text"; // this will throw a compile error
            }
            else if (type == "quote")
            {
                Quote quote = new Quote();
                item = quote; // allow item object to access the base class members...

                // these are NOT members of Post, so you cannot set them using Post object
                //item.source = (string)postType.ElementAt(1); // compile error
                //item.text = (string)postType.ElementAt(0);// compile error

                // these are members of Quote, so you can set them using a Quote object...
                quote.source = "key";
                quote.text = "value";
            }
            else // (type == "photo")
            {
                Photo photo = new Photo();
                item = photo;
            }

            // Now set members that are common to other three classes (RegularPost, Quote, and Photo)
            item.date = DateTime.Now.ToString();
            item.id = 12;

That is fine! I get it completely but then how would I access the child members outside the IF statement? While using Intellisense outside the loop, on the item variable, I cannot access the child functions.

My actual question is, how do I access child-specific functions outside the IF statement?

That is fine! I get it completely but then how would I access the child members outside the IF statement? While using Intellisense outside the loop, on the item variable, I cannot access the child functions.

My actual question is, how do I access child-specific functions outside the IF statement?

When you call the base class virtual function item.GetPostType() , it will invoke the overridden method from your specific class.

EDIT: Now you have me saying "function"--LOL. C# has methods, not functions... try to use the word "method" instead.

I tried accessing a property instead of a method and it gives this error-

Error 1 'Tumblarity.Post' does not contain a definition for 'title' and no extension method 'title' accepting a first argument of type 'Tumblarity.Post' could be found (are you missing a using directive or an assembly reference?)

You have not defined "title" for Quote and Photo, so how do you want to handle the scenario when the specific class is not RegularPost?

I am using an if statement as I previously mentioned and its probably there in the new piece of code that I pasted.

I am currently focusing on getting RegularPost working.

I got that error when I had commented out the if's for Photo and Quote so that is not an issue.

The error occurs because you have declared item as a variable of type 'Post'.
In order to access the members of its child type, you can cast it to the child type. As DdoubleD mentioned, you can use the GetPostType of the parent class to determine what you need to cast it t0. Use the following code after the if statement where you are trying to access the members of the child class:

if (item.GetPostType() == PostType.Regular)
            {
                string title = "";
                title = ((RegularPost)item).title;
            }

is that what you needed? :)

commented: Solved my problem! +1
commented: You got it! +17

Thanks a lot Ryshad! Your code solved my problem!

Thank you!

No problem. Remember to mark this thread as solved if you have found an answer to your question :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.