Как создать экземпляр объекта, который не включен в ваш проект C #? - PullRequest
4 голосов
/ 09 февраля 2011

Примечание. Весь пример кода значительно упрощен.

У меня есть DLL, определенная как:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;

namespace RIV.Module
{
    public interface IModule
    {
        StringWriter ProcessRequest(HttpContext context);
        string Decrypt(string interactive);
        string ExecutePlayerAction(object ParamObjectFromFlash);
        void LogEvent(object LoggingObjectFromFlash);
    }
}

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RIV.Module;

namespace RIV.Module.Greeting
{
    public class Module : IModule
    {
        public System.IO.StringWriter ProcessRequest(System.Web.HttpContext context)
        {
            //...
        }
        public string Decrypt(string interactive)
        {
            //...
        }
        public string ExecutePlayerAction(object ParamObjectFromFlash)
        {
            //...
        }
        public void LogEvent(object LoggingObjectFromFlash)
        {
            //...
        }
    }
}

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

Я пытаюсь создать его таким образом:

var type = typeof(RIV.Module.Greeting.Module);
var obj = (RIV.Module.Greeting.Module)Activator.CreateInstance(type);

Однако компилятор отрыгивает, потому что ссылка никогда не была установлена ​​на RIV.Module.Greeting.dll !

Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 09 февраля 2011

Вам нужно использовать больше отражений:

  • Загрузить сборку, вызвав Assembly.Load
  • Найти тип, позвонив someAssembly.GetType(name) или выполнить поиск someAssembly.GetTypes()
  • Передайте экземпляр Type на Activator.CreateInstance
  • Приведите его к своему интерфейсу.
1 голос
/ 09 февраля 2011

Вместо typeof (RIV.Module.Greeting.Module) попробуйте использовать

var type = Type.GetType("RIV.Module.Greeting.Module, RIV.Module.Greeting");

(т. Е. Загрузить тип, указав его полное в сборке имя в виде строки) и приведя к IModule.

Этот подход требует, чтобы вы знали точные имена классов и сборок модулей (как вы писали, они могли бы храниться в web.config).

В качестве альтернативы, вы могли бы пойти на полностью динамический подход к плагину:

  1. устанавливает соглашение о том, что все сборки модулей должны называться "RIV.Module.XYZ"
  2. проверять каталог bin на наличие соответствующих DLL
  3. для каждой библиотеки DLL,загрузите его (например, Assembly.Load) и просмотрите типы, реализующие IModule
  4. , создайте экземпляры всех найденных типов и приведите к IModule
...