Я могу объявить переменную Типа <T>, не указывая T во время компиляции?

Как я Загружаю класс "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?

5
задан Jeff Sternal 15 January 2010 в 15:42
поделиться

4 ответа

Предмет в <> должен быть типом, а не объектом.

Моя машина - это объект автомобиля типа, так что

Car myCar=new Car();

Я хочу, чтобы список мог хранить свои автомобили (объекты типа автомобиля).

List<Car> myCars = new List<Car>();

, а затем мы добавляем объект автомобиля типа в мой список.

 myCars.Add(myCar);
 myCars.Add(anotherCar);
7
ответ дан 18 December 2019 в 09:07
поделиться

Как я Загружаю класс "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();
5
ответ дан 18 December 2019 в 09:07
поделиться

Это способ динамически загрузки интерфейса. Это предполагает, что у вас есть какой-то способ получить сборку, вы пытаетесь загрузить его и строку для имени типа.

В моем случае я использовал файл 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;
}
1
ответ дан 18 December 2019 в 09:07
поделиться

Мне пришлось прочитать это несколько раз, но я понял, что вы спрашиваете. :) Этот вопрос является конкретным примером этого другого вопроса:

, который сказал, вот пример того, как вы можете использовать его для вашего теста. Очевидно, вы можете отличаться. Кроме того, не пропустите мою последнюю ноту в конце этого ответа.

Сборка 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
    {
    }
}

Сборка MyCompany.myproduct.mycomponent.myplementation:

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

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

Ваша программа в этой сборке в этой сборке, термин, который я вытащил из управляемой структуры расширения . Эта сборка ссылок 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);
        }
    }
}

Окончательное примечание:

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

  • относительно короткое кривое обучения.
  • Очень чистый код в результате.
  • Низкая стоимость выполнения (сборка мала, а производительность довольно хорошая).

Я легко рекомендую его как серьезное жизнеспособное вариант для тех, кто работает над новым приложением, если оно соответствует любому комбинации одного или нескольких из следующих:

  • Приложение делится на компоненты (как почти любое нетривиальное приложение будет быть).
  • Приложение должно быть гибким или расширяемым в будущем (как будет любой долгосрочный проект).
  • Приложение должно динамически загружать реализацию из неизвестной сборки.
5
ответ дан 18 December 2019 в 09:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: