Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Динамическое создание типов из DLL в C#  (Прочитано 8306 раз)
0 Пользователей и 1 Гость смотрят эту тему.
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« : 19-05-2010 11:00 » 

Здравствуйте форумчане! Вот зашел сегодня в тупик:

Есть интерфейс IShellSpecific, есть DLL в которой определен класс унаследованный от интерфейса IShellSpecific

Код:
   public class ShellSpecific : IShellSpecific
    {
        public ShellSpecific()
        {
            
        }

        public string ApplicationName
        {
            get { throw new NotImplementedException(); }
        }

        public XtraForm AboutForm
        {
            get { throw new NotImplementedException(); }
        }
   }

Загружаю эту библиотеку, экземпляр класса ShellSpecific  создается но к типу IShellSpecific не приводится! Причем если написать ShellSpecific is IShellSpecific возвращает true, но приведение вылетает с ошибкой что тип к интерфейсу преобразован быть не может, IsAssignableFrom возвращает false, вот код:

Код:
               Assembly assembly = Assembly.LoadFrom(dllFullFileName);
                Type[] types = assembly.GetExportedTypes();
                foreach (Type type in types)
                {
                    //Загрузка спецификации оболочки
                    if (typeof(IShellSpecific).IsAssignableFrom(type))
                    {
                        object shellSpecific = Activator.CreateInstance(type);
                        IShellSpecific iface = shellSpecific as IShellSpecific;
                        int t = 1;
                    }
                }

Как такое может быть??? Не надо
« Последнее редактирование: 19-05-2010 17:45 от RXL » Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 19-05-2010 11:44 » 

USBLexus, а зачем все эти танцы с бубном?

Код: (Text) C#.NET
IShellSpecific shellSpecific = new ShellSpecific();
Так работает?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #2 : 19-05-2010 16:33 » 

USBLexus, а зачем все эти танцы с бубном?

Все эти танцы с бубном потому что динамически подключаемая библиотека может содержать любые классы и иметь любое имя и путь, единственное что я о них знаю, это то что они реализуют интерфейс IShellSpecific

Внутри класса ShellSpecific данный код работает:
IShellSpecific shellSpecific = new ShellSpecific();
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 19-05-2010 19:50 » 

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

Итак, заводим одну общую сборку Common.dll, в которой присутствует интерфейс:
Код: (Text) C#.NET
namespace Common
{
    public interface ITest
    {
    }
}

Затем заводим сборку для динамической загрузки TestLib.dll, в которой существуют какие-то неизвестные классы, реализующие интерфейс общей сборки (естественно, эта сборка ссылается на Common.dll).
Код: (Text) C#.NET
using Common;

namespace DynamicLoadingTypes
{
    public class Test: ITest
    {
    }

    public class Test1 : Test
    {
    }
}

Наконец, пишем тестовое приложение TestApp.exe, которое ссылается на Common.dll, а TestLib.dll загружает динамически. Внутри него пишем тест, который перебирает типы загруженной сборки на совместимость с интерфейсом и, если совместимость установлена, создаёт экземпляры и приводит их к интерфейсу:
Код: (Text) C#.NET
        static IEnumerable<ITest> CreateInstances(string assemblyPath)
        {
            string iTestName = typeof(ITest).ToString();
            Type[] defaultConstructorParametersTypes = new Type[0];
            object[] defaultConstructorParameters = new object[0];
            Assembly assembly = Assembly.LoadFile(assemblyPath);
            foreach (Type type in assembly.GetTypes())
            {
                if (type.GetInterface(iTestName) != null)
                {
                    ConstructorInfo defaultConstructor = type.GetConstructor(defaultConstructorParametersTypes);
                    object instance = defaultConstructor.Invoke(defaultConstructorParameters);
                    yield return instance as ITest;
                }
            }
        }

        static void Test(string assemblyName)
        {
            foreach (ITest instance in CreateInstances(assemblyName))
            {
                Console.WriteLine(instance.ToString());
            }
        }
И убеждаемся, что всё работает.
« Последнее редактирование: 19-05-2010 19:52 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #4 : 20-05-2010 08:02 » 

Именно так у меня все и сделано, а как по другому то? Не работает, говорю же
Есть у меня одно подозрение что библиотека Common.dll одна и таже но берется из 2х разных мест может в этом проблема, сегодня проверить возможности нет, гляну завтра
« Последнее редактирование: 20-05-2010 08:04 от USBLexus » Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #5 : 21-05-2010 09:21 » 

Есть у меня одно подозрение что библиотека Common.dll одна и таже но берется из 2х разных мест может в этом проблема, сегодня проверить возможности нет, гляну завтра

Да, дело было именно в этом
« Последнее редактирование: 21-05-2010 09:34 от USBLexus » Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #6 : 28-05-2010 15:30 » 

USBLexus,

как раз разбираюсь с темой "reflection".
Попробовала твой пример, немного усложнив (как оказалось) - внесла в интерфейс функцию
Код:
  void testFunc_ICommon();

Затем в классе Test реализовала:
Код:

 public void testFunc_ICommon()
 {
   Console.WriteLine("TestICommon::testFunc_ICommon() was called >>>>>>>>>>>");
 }

А в классе Test1 перегрузила:
Код:
new public void testFunc_ICommon()
 {
Console.WriteLine("TestICommon::testFunc_ICommon_2() was called >>>>>>>>>>>");
 }

Ну и напоследок для теста в функции Test() добавила:
Код:
  instance.testFunc_ICommon();
       
После чего возник вопрос:
почему при получении инстанции классе Test1 вызывается функция класса Test (т.е. перегрузка не срабатывает)?
Что тут криво?
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 29-05-2010 08:50 » 

Malaja, потому что функцию нужно объявить виртуальной, и перегружать не через new, а через override.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #8 : 31-05-2010 08:02 » 

Дим,
спасибо!
Я ступила - я сначала ее сделала виртуальной, но вместо override написала сразу new. А когда оно не сработало, вообще убрала virtual...
Все-таки c++ и c# "немного" отличаются... Воистину - "учите матчасть" Ага
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines