Я должен был прочитать это несколько раз, но я понял, о чем ты спрашиваешь. :) Этот вопрос является частным случаем этого другого вопроса:
Тем не менее, вот пример того, как вы можете использовать его для своего теста. Очевидно, вы можете изменить это. Кроме того, не пропустите мою последнюю заметку в конце этого ответа.
Assembly MyCompany.MyProduct.MyComponent:
Определите ваши интерфейсы в этой сборке:
namespace MyCompany.MyProduct.MyComponent
{
public interface IMyObjectInterface
{
void MyObjectMethod();
}
/* It's important to include this non-generic interface as a base for
* IMyContentInterface<T> because you will be able to reference this
* in the assembly where you load components dynamically.
*/
public interface IMyContentInterface
{
Type ObjectType
{
get;
}
void MyContentMethod();
}
public interface IMyContentInterface<T> : IMyContentInterface
where T : IMyObjectInterface
{
}
}
Assembly MyCompany.MyProduct.MyComponent.Implementation:
Реализация интерфейсов в этой сборке, которые будут динамически загружаться.
namespace MyCompany.MyProduct.MyComponent
{
public abstract class MyAbstractObject : IMyObjectInterface
{
public abstract void MyObjectMethod();
}
public class MyObject : MyAbstractObject
{
public override void MyObjectMethod() { }
}
public abstract class MyAbstractContent<T> : IMyContentInterface<T>
where T : MyAbstractObject
{
public Type ObjectType
{
get
{
return typeof(T);
}
}
public abstract void MyContentMethod();
}
public class MyContent : MyAbstractContent<MyObject>
{
public override void MyContentMethod() { }
}
}
Сборка MyCompany.MyProduct
Ваша программа состоит из в этой сборке, термин, который я извлек из Managed Extensibility Framework . Эта сборка ссылается на MyCompany.MyProduct.MyComponent
, но не MyCompany.MyProduct.MyComponent.Implementation
в предположении, что интерфейсы с большей вероятностью останутся совместимыми , чем реализации во время разработки продукта. Этот дизайн является попыткой отдать предпочтение сплоченности по сравнению с (парой часто неправильно понятых слов), но фактические реализации, как правило, сильно различаются по успешности достижения этой цели.
namespace MyCompany.MyProduct
{
using MyCompany.MyProduct.MyComponent;
using System.Reflection;
using System.Security.Policy;
public class ComponentHost
{
public void LoadComponents()
{
Assembly implementation = LoadImplementationAssembly();
/* The implementation assembly path might be loaded from an XML or
* similar configuration file
*/
Type objectType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyObject");
Type contentType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyContent");
/* THIS assembly only works with IMyContentInterface (not generic),
* but inside the implementation assembly, you can use the generic
* type since you can reference generic type parameter in the source.
*/
IMyContentInterface content = (IMyContentInterface)Activator.CreateInstance(contentType);
}
private Assembly LoadImplementationAssembly()
{
/* The implementation assembly path might be loaded from an XML or
* similar configuration file
*/
string assemblyPath = "MyCompany.MyProduct.MyComponent.Implementation.dll";
return Assembly.LoadFile(assemblyPath);
}
}
}
Заключительная нота:
Платформа Managed Extensibility Framework была создана как общее решение проблемы, над которой вы работаете. Проработав некоторое время, я с уверенностью говорю, что он обладает следующими хорошими свойствами:
- Относительно короткая кривая обучения.
- В результате получился очень чистый код.
- Низкие затраты времени выполнения (сборка небольшая, производительность неплохая).
Я бы легко порекомендовал его как серьезный жизнеспособный вариант для тех, кто работает над новым приложением, если оно удовлетворяет любой комбинации из одного или нескольких из следующих:
- Приложение разделено на компоненты (как было бы почти любое нетривиальное приложение).
- Приложение должно быть гибким или расширяемым в будущем (как любой долгосрочный проект).
- Приложение должно динамически загружать реализацию из неизвестной сборки.