none
как получить доступ к полю родительского объекта? RRS feed

  • Вопрос

  • Доброго времени суток!
    Сразу уточню: вопрос не про наследование, а про отношения parent/child

    Задача - получить значения поля из родительского объекта в конструкторе дочернего, но с условием, что у конструктора дочернего не может быть параметров (используется внешняя библиотека xml-rpc)

    код примерно такой:

       public class ParentClass
        {
            public string someField = "string";
            ChildClass[] child_array;
     
            public ParentClass ()
            {
                child_array = somefunc(); // xml-rpc запрос, возвращающий коллекцию объектов
            }
        }
     
        public class ChildClass
        {
            public ChildClass () // параметров быть не может
            {
                // здесь нужно получить значение someField
            }
        }

    вот здесь нашёл отличное решение, но не подходит, т.к. мне нужно получить значение ещё в конструкторе
    модет быть кто-нибудь подскажет изящное решение? Был бы очень благодарен 

    10 сентября 2012 г. 15:13

Ответы

  • Ок, стало понятнее.

    Но, к сожалению, в вашем случае, иметь в конструкторе информацию о сайте, не имея ссылки на сайт (вы не хотите передавать параметры в конструктор класса описывающего курс), можно только не очень красивыми способами:

    1. Если вы в единицу времени обрабатываете один сайт, то можно сделать статический класс, со статическим полем, типа сайт. Из классов курсов вы сможете получить к нему доступ.

    2. Хранить информацию о пути и т.д. во внешних хранилищах. Например, в файле.

    Но, я бы выбрал, передавать в конструктор класса курс, ссылку на объект класса сайт.

    • Помечено в качестве ответа Kenaut 12 сентября 2012 г. 17:24
    10 сентября 2012 г. 17:33
    Отвечающий
  • Привет.

    Еще можно пройтись по всему дереву вашего сайта(ов) и переформировать данные в нужный вам вид. Если ничего больше не получится и не выйдет пробросить ссылку на класс "родитель".

    По-моему даже через рефлексию не выйдет получить объект класса, который является хранилищем. Также либо обойти все дерево, либо ответ Алексея выше.


    Для связи [mail]

    • Помечено в качестве ответа Kenaut 12 сентября 2012 г. 17:24
    12 сентября 2012 г. 7:25

Все ответы

  • Добрый день.

    Не очень понял с чем проблема, но может вот так попробовать:

    public class ChildClass : ParentClass
        {
            public ChildClass () : base()
            {
                // получаете значение someField
            }
        }



    10 сентября 2012 г. 15:19
    Отвечающий
  • Добрый день.

    Не очень понял с чем проблема, но может вот так попробовать:

    public class ChildClass
        {
            public ChildClass () : base()
            {
                // получаете значение someField
            }
        }

    :) спасибо за сочувствие, но, повторюсь, вопрос НЕ о наследовании

    10 сентября 2012 г. 15:25
  • У вас сейчас два класса, вообще не связанные между собой. Получить из одного класса доступ к полю/свойству другого класса, можно только через три механизма:

    1. Наследование (почему он вам не подходит, не очень понятно)

    2. Объявление скрытого поля в классе "чилд" типа класса "предок", с предоставлением интерфейсов только к нужным членам вложенного класса. В терминах петтернов, это называется "включение". Например:

    public class ParentClass
        {
            public string someField = "string";
            ChildClass[] child_array;
     
            public ParentClass ()
            {
                child_array = somefunc(); // xml-rpc запрос, возвращающий коллекцию объектов
            }
        }
     
        public class ChildClass
        {
            ParentClass _field;
            public ChildClass () 
            {
                _field = new ParentClass();
                Console.WriteLine(SomeField);
            }
    
            public string SomeField
            {
                get
                {
                     return _field.someField;
                }
            }
        }

    3.  Обявить в методе локальную переменную типа "родитель". Аналогично 2, но не надо объявлять поле, сразу в конструкторе объявляете переменную и используете ее:

        public class ChildClass
        {
            public ChildClass () 
            {
                ParentClass _field = new ParentClass();
                Console.WriteLine(_field.someField);
            }
        }

    Если вам не подходит ни один из предложенных вариантов, то вам необходимо уточнить, какая цель стоит перед вами.
    • Предложено в качестве ответа YatajgaEditor 11 сентября 2012 г. 5:40
    10 сентября 2012 г. 15:39
    Отвечающий
  • понял, описываю задачу:

    есть сайт, сайт делится на курсы, курсы делятся на разделы, они делятся на занятия, которые делятся на файлы (это всё не моё), инфа о всей этой прелести забирается мной через xml-rpc, кстати сайтов больше одного

    программа сливает те самые файлы и раскидывает их по папочкам в соответствии с этой иеархией

    объект сайт (родительский) инициализируется гораздо раньше его содержимого(курсов и т.д.) и, в частности, содержит путь к папочке, где будет выстроено дерево из каталогов

    дальше один из методов сайта через http запрос получает информацию о содержимом сайта (курсы и т.д.)

    у объект курса есть конструктор, который должен создать папочку для себя, у объекта раздела - тоже самое, а занятие себе папочку создаёт и свои файлы скачивает с сервера в неё

    т.е. передать someField мне нужно несколько раз, и я уверен, что хитрый способ должен быть :) думаю, понятно объяснил почему ни один из Ваших методов мне не подхоидт

    конечно, можно иметь отдельный (имхо лишний) объект представляющий собой дерево, но хотелось бы всё же услышать мнения гуру :)

    10 сентября 2012 г. 16:07
  • Ок, стало понятнее.

    Но, к сожалению, в вашем случае, иметь в конструкторе информацию о сайте, не имея ссылки на сайт (вы не хотите передавать параметры в конструктор класса описывающего курс), можно только не очень красивыми способами:

    1. Если вы в единицу времени обрабатываете один сайт, то можно сделать статический класс, со статическим полем, типа сайт. Из классов курсов вы сможете получить к нему доступ.

    2. Хранить информацию о пути и т.д. во внешних хранилищах. Например, в файле.

    Но, я бы выбрал, передавать в конструктор класса курс, ссылку на объект класса сайт.

    • Помечено в качестве ответа Kenaut 12 сентября 2012 г. 17:24
    10 сентября 2012 г. 17:33
    Отвечающий
  • Спасибо, идея со статическим классом интересна, но вряд ли: объекты представляющие сайты у меня создаются на этапе запуска программы (десериализуются из конфига), да и вообще :)

    Внешним хранилищем сейчас является другой объект :) Но как Вы и сказали, не очень красивый способ, ищу другие варианты, должно же быть что-то изящное для этого случая

    А в конструктор, как уже говорил, передать ничего нельзя - ограничение библиотеки

    10 сентября 2012 г. 18:35
  • А в конструктор, как уже говорил, передать ничего нельзя - ограничение библиотеки


    Не очень понятно, что за ограничение. Ограничение по требованиям? Ведь насколько я понял, вы сами пишите этот класс?
    10 сентября 2012 г. 19:11
    Отвечающий
  • По моему Вы сами пытаетесь усложнить себе жизнь. Из  высше изложенного, ели это действительно так, классическая проблема, решается наследованием. Самое красивое решние, как Вы выразились, это наследованение, как уже ответил Алексей. А вот почему оно Вам не подходит, непонятно. Докажите обратное, и я постараюсь привести другой вариант реализации.
    10 сентября 2012 г. 19:38
    Модератор
  • Yatajga, я не пойму, что от кого Вы предлагаете наследовать? курс от сайта, раздел от курса, а занятие от раздела? тогда не пойму зачем мне в занятии иметь поля и методы сайта, курса и раздела - они там абсолютно не нужны... только одно поле. На сколько я знаю наследование используется от общего к частному, так это совсем не мой случай.

    Или я не правильно понимаю Ваше предложение?

    Алексей, xml-rpc библиотеку я взял готовую, идея в том, что она получает ответ от сайта и вызывает непараметраризированный (так кажется) конструктор класса, чтобы десериализовать этот самый ответ в объект

    11 сентября 2012 г. 13:35
  • Действительно, наследование в вашем случае не подойдет.

    Насколько я понял, вы получает объект "сайт" из библиотеки. Остальные классы уже ваши. Никто вам не мешает определить в них конструктор, который будет принимать парметр типа "сайт" и дальше хранить и обрабатывать его.

    Или классы курсов у вас тоже создает библиотека?

    11 сентября 2012 г. 17:00
    Отвечающий
  • как-то так, вроде ничего не напутал :)

    using CookComputing.XmlRpc;
    
    public interface IXmlRpcMyProxy : IXmlRpcProxy
    {
    	[XmlRpcMethod]
    	Course[] get_cources (int userid);
    }
    
    public class Site : TreeNode
    {
    	IXmlRpcMyProxy proxy = XmlRpcProxyGen.Create<IXmlRpcMyProxy> ();
    	Course[] SiteCourses;
    
    	public Site ()
    	{
    	}
    	
    	public void Update ()
    	{
    		SiteCourses = proxy.get_cources (site.userid);
    	}
    }
    
    public class Course
    {
    	public Section[] CourseSections;
    
    	public Course ()
    	{
    	}
    }
    
    public class Section
    {
    	public Activity[] CourseActivities;
    
    	public Section ()
    	{
    	}
    }
    
    public class Activity
    {
    	public Activity ()
    	{
    	}
    }

    всё дерево объектов создаётся здесь :
    SiteCourses = proxy.get_cources (site.userid);

    • Изменено Kenaut 11 сентября 2012 г. 18:27
    11 сентября 2012 г. 18:19
  • Привет.

    Еще можно пройтись по всему дереву вашего сайта(ов) и переформировать данные в нужный вам вид. Если ничего больше не получится и не выйдет пробросить ссылку на класс "родитель".

    По-моему даже через рефлексию не выйдет получить объект класса, который является хранилищем. Также либо обойти все дерево, либо ответ Алексея выше.


    Для связи [mail]

    • Помечено в качестве ответа Kenaut 12 сентября 2012 г. 17:24
    12 сентября 2012 г. 7:25
  • всем большое спасибо за помощь, очевидно ошибка в проектировании, буду использовать по два класса для каждого объекта, как и было раньше :(
    12 сентября 2012 г. 17:24