Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Записать класс как переменную


Автор: DenWPF 5.4.2010, 12:10
Сложно объяснить проще показать.

вот у меня есть список 
"bit.ly",
            "j.mp",
            "u.nu",
            "kl.am "

для каждого элемента свой класс.

я не хочу делать конструкцию:
Код

if(a == "bit.ly")
   Bit_ly c = new Bit_ly();
else if ...

можно это как то по другому сделать.



Автор: Mephisto 5.4.2010, 12:54
Можно сделать Dictionary по принципу string, Type. По ключу получать тип и инстанциорвать уже потом.
Либо просто фабричный метод со switch'ом.

Добавлено через 1 минуту и 6 секунд
Семантически то на то и выйдет. Только первый случай не читается глазками. В случае лага только отладчик поможет.

Автор: mrbrooks 5.4.2010, 13:40
От чего бы в самом списке не хранить сами объекты. С перегруженным ToString() для более удобоваримого внешнего вида. 

Автор: azesmcar 5.4.2010, 13:54
Цитата(DenWPF @  5.4.2010,  12:10 Найти цитируемый пост)
можно это как то по другому сделать.

http://msdn.microsoft.com/en-us/library/ee817667.aspx

Автор: mihryak 5.4.2010, 20:13
Цитата(azesmcar @  5.4.2010,  14:54 Найти цитируемый пост)

Factory design pattern 

открываем и видим
Код

      if(args.Length > 0 && args[0] == "BrandX")
         factory = new BrandXFactory();
      else
         factory = new ConcreteComputerFactory();

т.е. от разбора всех вариантов фабрика не спасает, но почему-то её часто преподносят в качестве панацеи от сабжевой проблемы
едиственное (и самое важное и полезное), что она даёт, - это локализация кода, разбирающего варианты, в одном месте

а так, оба способа Mephisto гораздо симпатичнее кучи if-else

Автор: DenWPF 5.4.2010, 20:14
ясно...проще через ифы

Автор: diadiavova 5.4.2010, 21:33
Цитата(DenWPF @  5.4.2010,  21:14 Найти цитируемый пост)
ясно...проще через ифы

Вообще-то в ряде случаев код можно упростить и даже обойтись без ифов, но для того, чтобы что-то конкретное предложить надо иметь немного больше информации. Например непонятно откуда берётся список строк, по которым надо строить объекты. Если ты их получаешь откуда-то именно в таком виде, то будет одно решение, а если ты сам придумал таким незамысловатым способом хранить информацию о типах - другое. Так же неплохо было бы выяснить какая связь между классами,, экземпляры которых надо строить(например расположены они в однойсборке и пространстве имён или в разных, или они имеют общего предка или как-то ещё объединены), кроме того, из кода можно вроде бы сделать вывод, что имя класса можно получить заменой точки на знак подчёркивания, но вопрос работает ли это для всех строк. 
И потом не очень понятно, что значит "я не хочу делать...", есть какие причины для этого или просто "не хочу и всё"?

Автор: DenWPF 5.4.2010, 23:39
причина если объектов..т.е классов будет 100... ифы будут мягко говоря не удобны.
да правельно заметили если заменить, "." на "_" и первая буква заглавная и если первая не буквы а цифра то поставить перед ней "_"

3.ui = _3_ui

это все беру из писка куда сам все записываю, всё находится в одной сборке и под одним неймспэйсом


Автор: diadiavova 5.4.2010, 23:48
Совсем другое дело. Тогда твоя проблема решается стандартными инструментами.
Если есть возможность вместо странных строк с заменой символов использовать другие, то надо так и сделать. Для класса по имени Bit_ly надо хранить строку, которую возвратит выражение
Код

typeof(Bit_ly).ToString();

Для других то же самое. Создать объект по такой строке можно выражением
Код

Activator.CreateInstance( Type.GetType("здесь сохранённая строка"));


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

Автор: azesmcar 5.4.2010, 23:54
Цитата(mihryak @  5.4.2010,  20:13 Найти цитируемый пост)
а так, оба способа Mephisto гораздо симпатичнее кучи if-else 


то, что описал Mephisto и есть одна из реализаций шаблона "фабрика". Я назвал имя, что было легче искать.

Автор: DenWPF 6.4.2010, 00:00
diadiavova, я примерно понял, но все равно не догнал как сделать. да и вообще читаю ваши посты и понимаю что не понимаю даже не которых терминах.
Пора наверное переходить из пользовательского программирования. в личку кинте что почитать.

Автор: diadiavova 6.4.2010, 00:02
Цитата(DenWPF @  6.4.2010,  01:00 Найти цитируемый пост)
 в личку кинте что почитать.

Честно говоря понятия не имею, в принципе всё есть в мсдн.
Тогда пиши что непонятно постараюсь объяснить "на пальцах".

Автор: DenWPF 6.4.2010, 00:08
думаю достаточно будет примера. есть строка "bit.ly"
к примеру уже есть функция которая её переделывает в нужный формат(имя класса)
Bit_ly.
как теперь мне создать объект такого класса?


Автор: diadiavova 6.4.2010, 01:02
Для начала...в предыдущем примере я немного ошибся, там вместо ToString тфдо использовать свойство AssemblyQualifiedName
Код

typeof(Bit_ly).AssemblyQualifiedName;


Цитата(DenWPF @  6.4.2010,  01:08 Найти цитируемый пост)
к примеру уже есть функция которая её переделывает в нужный формат(имя класса)
Bit_ly.
как теперь мне создать объект такого класса?

Я честно говоря так и не понял какая необходимость есть в том, чтобы хранить строки в таком ненадёжном формате. Для начала разжую мою идею.
Возьмём класс Button из винформ. 
Код

var buttonstring = typeof(Button).AssemblyQualifiedName;

Выполнив такое присвоение ты получишь в переменной buttonstring следующую строку
Код

System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Эта строка полностью описывает тип в сборке и именно её и надо хранить в коллекции. Для любого своего класса ты можешь получить подобную строку тем же способом.
Далее для того, чтобы создать по этой строке кнопку надо выполнить код
Код

var t = Type.GetType(typestring);
var b =  Activator.CreateInstance(t);

Где typestring - как раз и есть переменная с этой строкой.

То есть иными словами по такой строке ты создаёшь экземпляр типа Type, а уже из него при помощи активатора экземпляр целевого типа(в данном случае Button).

Теперь пара слов о том, как получить полный список таких строк, скажем для классов расположенных в одном пространстве имён.

В принципе для выполнения подобных операций тебе надо ознакомиться с пространством System.Reflection и классом System.Type.
Общий принцип такой:
Сначала надо получить экземпляр класса Assembly для сборки, в которой все эти типы описаны. Для этого надо воспользоваться статическими методами самого класса Assembly, например для получения ссылки на ту сборку, в которой выполняется код, можно использовать метод GetExecutingAssembly, то есть этот класс и его члены тебе надо будет изучить. Другой вариант получения ссылки на нужную сборку - через тип, который определён в ней, для твоего случая тебе должен помоч такой код

Код

var asm = typeof(Bit_ly).Assembly;

Получив ссылку на сборку ты можешь вызвать у неё метод GetTypes, который возвратит тебе массив объектов Type, для каждого типа, определённого в этой сборке. Дальше массив можно отфильтровать и получить только те типы, которые нужны и преобразовать их в строки(если надо, поскольку в конечном итоге тебе придётся работать с типами, а не со строками.
Ну если например надо сохранять в файл, то коллекцию нужных строк можно получить так
Код

         var typestrings = from tp in asm.GetTypes()
                           where tp.Namespace == "Namespacestring"
                           select tp.AssemblyQualifiedName;

Но если этот список нужен только во время исполнения, то лучше хранить в коллекции типы, а не строки
Код

         var typestrings = from tp in asm.GetTypes()
                           where tp.Namespace == "Namespacestring"
                           select tp;

Автор: azesmcar 6.4.2010, 01:04
Код

namespace MyNamespace
{
    interface IBase
    {
        void foo();
    }

    class Test : IBase
    {
        public Test()
        {
            Console.WriteLine("test");
        }
        public void foo()
        {
            Console.WriteLine("foo");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string typeName = "MyNamespace.Test";
            IBase b = (IBase)Activator.CreateInstance(Type.GetType(typeName));
            b.foo();
        }
    }
}


Добавлено через 27 секунд
diadiavova уже ответил smile

Автор: DenWPF 6.4.2010, 11:13
можно вызвать без интерфейса
string a = "Bit_ly";
var t = Type.GetType(a);
var b = Activator.CreateInstance(t);


Bit_ly.SetName();
b.SetName(); - не пашет=(

Автор: diadiavova 6.4.2010, 18:35
DenWPF, вот о чём ты сейчас? smile Вроде разжевал уже не знаю куда дальше.

Автор: DenWPF 6.4.2010, 21:13
та я тоже думал что все понятно...
ну как вызвать метод статический ??
Код

var t = Type.GetType(typestring);
var b =  Activator.CreateInstance(t);

b.метод ? - не пашет

Автор: diadiavova 6.4.2010, 21:24
Ну у меня ведь пашет

Добавлено через 4 минуты и 18 секунд
Не забывай о том, что переменная b типизируется как object. Поэтому вызвать напрямую метод без приведения типов не получится. Мне показалось, что это очевидно.

Автор: DenWPF 6.4.2010, 21:54
всё понял. без интерфейса не как...
спасибо было вкусненько=)

Автор: diadiavova 6.4.2010, 21:56
Цитата(DenWPF @  6.4.2010,  22:54 Найти цитируемый пост)
без интерфейса не как...

Ну не то, чтобы совсем никак...просто лучше делать правильно.

Автор: DenWPF 6.4.2010, 21:59
ну так приведения типа не как не сделаешь...

Автор: diadiavova 6.4.2010, 23:06
Цитата(DenWPF @  6.4.2010,  22:59 Найти цитируемый пост)
ну так приведения типа не как не сделаешь... 

Ну тебе ведь не это нужно. Если надо вызывать у всех классов одноимённый метод, то способ это сделать есть. Код из аттача можно было написать итак
Код

            var t = Type.GetType(textboxstring);
            var tb = Activator.CreateInstance(t);
            tb.GetType().GetProperty("Parent").SetValue(tb, this,null);
            tb.GetType().GetMethod("AppendText").Invoke(tb, new string[] { "И что не пашет?" });

Автор: DenWPF 6.4.2010, 23:11
ого жестко...блин учиться и учиться...спасибо.

Автор: diadiavova 6.4.2010, 23:15
Цитата(DenWPF @  7.4.2010,  00:11 Найти цитируемый пост)
ого жестко

Вот поэтому и говорю, что лучше делать правильно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)