Activator.CreateInstance с унаследованным классом не в том же проекте

У меня есть решение, которое содержит два проекта. Сначала позвольте мне описать мой сценарий. Проект 1: содержит вызовы базового класса MyBaseClass со следующими двумя интересующими меня свойствами и методом:

TypeToLoad — статическое строковое свойство, унаследованный класс которого необходимо создать с помощью простой функции получения/установки.

Экземпляр — статическое свойство, которое возвращает экземпляр MyBaseClass типа, указанного в TypeToLoad, со следующими строками кода:

public static MyBaseClass Instance{
   return (MyBaseClass)Activator.CreateInstance(Type.typeof(TypeToLoad));
}

теперь во втором проекте я наследую MyBaseClass следующим образом (конечно, было добавлено правильное пространство имен и ссылки).

public class MyInheritClass : MyBaseClass {
    //implements all other functions of MyBaseClass;
}

и один из моих других файлов кода в том же проекте, что и MyInheritClass, у меня есть следующие строки кода:

Type myType = Type.typeof("MyInheritClass"); //returns the correct "Type"
MyBaseClass.TypeToLoad = "MyInheritClass";
MyBaseClass myInstance = MyBaseClass.Instance; //Errors... because Type.typeof(...) could not resolve "MyInheritClass".

Когда я перемещаю файл кода MyInheritClass в тот же проект, что и MyBaseClass, код работает нормально.

Мой вопрос в том, есть ли способ создать экземпляр MyInheritClass с использованием MyBaseClass.Instance, установив MyBaseClass.TypeToLoad = "MyInheritClass" без необходимости иметь эти два класса в одном проекте (MyBaseClass в базовой библиотеке классов DLL и MyInheritClass в другом проекте ссылка на библиотеку DLL MyBaseclass)?

Я пытался искать отражения, активатор, но не смог найти то, что искал. Может быть, я не знаю правильную терминологию для этого.


person NPToita    schedule 27.03.2012    source источник
comment
Кстати, вам действительно следует использовать описательные теги, такие как .net или c#. Если бы вы это сделали, то, скорее всего, получили бы ответ намного раньше.   -  person svick    schedule 27.03.2012


Ответы (1)


Предполагая, что вы на самом деле имеете в виду Type.GetType() (а не Type.typeof(), который не будет компилироваться ), то он четко задокументирован как делающий именно то, что вы наблюдаете:

Полное сборкой имя типа, которое требуется получить. […] Если тип находится в текущей выполняемой сборке или в Mscorlib.dll, достаточно указать имя типа, уточненное его пространством имен.

Там же объясняется, как это исправить: добавить имя сборки к имени типа. Итак, если ваш тип вызывается в MyInheritClass, он находится в пространстве имен MyNamespace и в сборке MyAssembly (обычно совпадает с именем проекта), вы можете установить имя типа в

MyNamespace.MyInheritClass, MyAssembly

и это должно работать.

Кроме того, вам следует избегать использования строк для имен типов, использование реальных объектов Type намного безопаснее. TypeToLoad должен быть типа Type, а не string.

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

person svick    schedule 27.03.2012
comment
Привет, Свик, ты абсолютно прав насчет моей ошибки ввода Type.TypeOf() вместо Type.GetType(). - person NPToita; 27.03.2012
comment
Цель моего движения в этом направлении заключается в том, что у меня есть набор провайдеров, которые будут моей базой/ядром с функциональностью по умолчанию. И для каждого клиента, который у меня есть, я бы наследовал этих провайдеров по мере необходимости и переопределял их виртуальные методы, когда это было необходимо, и в файле конфигурации указывал тип провайдера на правильный класс провайдера клиента. И я не хочу объединять всех клиентов в одну сборку, потому что нет смысла позволять библиотеке клиента А также содержать код клиента Б. - person NPToita; 27.03.2012
comment
Представьте, если количество клиентов достигнет 100+, управлять набором кодов будет адски сложно. Переходя к этому прямому, это дает мне возможность разрабатывать каждого поставщика клиента отдельно в своем собственном проекте и просто выгружать DLL в свое клиентское приложение и указывать поставщика на класс клиента. Что-то похожее на поставщиков членства. Спасибо за ваше решение/предложение. Я обязательно попробую это и дам отзыв об этом. Я симпатичный, у другого тела есть та же проблема, что и у меня. Еще раз большое спасибо. Тин П. Нгуен - person NPToita; 27.03.2012
comment
svick, Ваше решение работает как шарм. Все, что мне нужно сделать, это изменить в файле конфигурации параметры с ‹pageEvents providerType=RepSpark.Web.PageEvents.client1PageEventProvider/› на ‹pageEvents providerType=RepSpark.Web.PageEvents.client1PageEventProvider, App_Code/›, как вы понимаете, это проект сайта. - person NPToita; 27.03.2012
comment
Я не говорю, что вы должны поместить весь код в одну сборку. Я просто говорю, что вы можете использовать другой подход к настройке используемой реализации. Вы видели контейнер IoC, такой как Castle Windsor? - person svick; 27.03.2012