Как я Загружаю класс "MyContent" динамично? Я имею 1 interface<T>
, 1 абстрактный дженерик class<T>
и 1 класс. Проверьте мой код:
public interface IMyObjectInterface{
}
public abstract MyAbstractObject : IMyObjectInterface{
}
public class MyObject : MyAbstractObject{
}
public interface IMyContentInterface<T> where T : MyAbstractObject
{
void MyMethod();
}
public abstract MyAbstractContent<T>, IMyContentInterface<T> where T : MyAbstractObject
{
public abstract void MyMethod();
}
public public class MyContent : MyAbstractContent<MyObject>
{
public override void MyMethod() { //do something }
}
Я пробую, но очевидно это не работает:
IMyObjectInterface obj = (IMyObjectInterface)Assembly.Load("MyAssembly").CreateInstance("MyObject");
IMyContentInterface<obj> content = (IMyContentInterface<obj>)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
//assembly and type names are correct
Если я изменяюсь IMyContentInterface<obj>
кому: IMyContentInterface<MyObject>
, работы:
IMyContentInterface<MyObject> content = (IMyContentInterface<MyObject>)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
//assembly and type names are correct
Проблема состоит в том, что я не делаю то, что будет моим объектом в 2-й строке при определении IMyContentInterface<T>
. Кто-то знает, как сделать это в Платформе.NET 4.0?
Предмет в <>
должен быть типом, а не объектом.
Моя машина - это объект автомобиля типа, так что
Car myCar=new Car();
Я хочу, чтобы список мог хранить свои автомобили (объекты типа автомобиля).
List<Car> myCars = new List<Car>();
, а затем мы добавляем объект автомобиля типа в мой список.
myCars.Add(myCar);
myCars.Add(anotherCar);
Как я Загружаю класс "MyContent" динамично?
Загрузка это не твердо - вы уже знаете, как сделать, это, но дженерики C# со строгим контролем типов, проверяется и гарантируемое во время компиляции. Рассмотреть этот код:
List<string> list = new List<string>();
list.Add(new TcpSocket()); // This line won't compile
компилятор C# не мог сказать вам, что это было недопустимо, если вам разрешили объявить дженерики как это:
Type type = GetTypeFromReflectedAssembly();
List<type> list = new List<type>();
// This *might* work - who knows?
list.Add(new TcpSocket());
, Если ваша конечная цель должна звонить MyContent. MyMethod ()
и это не имеет никакого отношения к универсальному параметру типа
, рассматривает объявление неуниверсального интерфейса, который можно реализовать где-нибудь в иерархии наследования и объявить переменную экземпляра с помощью этого:
IMyContentInterface content = (IMyContentInterface)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
Это способ динамически загрузки интерфейса. Это предполагает, что у вас есть какой-то способ получить сборку, вы пытаетесь загрузить его и строку для имени типа.
В моем случае я использовал файл XML. Вы можете использовать любой, я не показываю эти методы, потому что он может измениться на вашу реализацию.
ISomeInterface myInterface = this.GetComponent<ISomeInterface>("SomeImplementation");
public T GetComponent<T>(string componentName)
{
// A method to dymanicly load a .dll, not shown in this example
Assembly assembly = this.GetComponentAssembly(componentName);
// A method to get a string assembly type, in this case from another source
string assemblyType = this.GetAssemblyType(componentName);
T component = (T)assembly.CreateInstance(assemblyType);
return component;
}
Мне пришлось прочитать это несколько раз, но я понял, что вы спрашиваете. :) Этот вопрос является конкретным примером этого другого вопроса:
, который сказал, вот пример того, как вы можете использовать его для вашего теста. Очевидно, вы можете отличаться. Кроме того, не пропустите мою последнюю ноту в конце этого ответа.
Определите ваши интерфейсы в этой сборке:
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
{
}
}
Реализуйте интерфейсы в этой сборке, которые будут динамически загружаться.
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.mycomponent
, но не mycompany.myproduct.mycomponent.mypredation
Под предположением, что интерфейсы более склонны оставаться , совместимыми , чем реализации во время разработки продукта. Эта конструкция представляет собой попытку поддержать сплоченность над сцеплением (пара часто неправильно понятых слов), но фактические реализации, как правило, сильно различаются в зависимости от их успеха достижения этой цели.
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);
}
}
}
Структура расширения была построена в виде общего решения проблемы, над которой вы работаете. Сейчас работая с ним сейчас, я говорю с уверенностью, что он имеет следующие приятные свойства:
Я легко рекомендую его как серьезное жизнеспособное вариант для тех, кто работает над новым приложением, если оно соответствует любому комбинации одного или нескольких из следующих: