Передача параметров / свойств с помощью MEF - PullRequest
0 голосов
/ 15 марта 2012

Рассмотрим следующий пример:
У меня есть Car класс и ILogger интерфейс. Я бы хотел, чтобы реализации ILogger записывали (console, file, db и т. Д.) Список спецификаций автомобилей. И, конечно же, я хочу использовать MEF для ILogger. Но для регистрации мой класс регистратора должен иметь доступ к спецификации автомобиля. И я не уверен, что будет лучшим способом передать объекты в мои классы регистратора. Чтобы быть более понятным, вот код:

class Program
{
    public class Car
    {
        public string Brand { get; set; }
        public string Model { get; set; }
    }

    private CompositionContainer _container;

    [Import(typeof(ILogger))]
    public ILogger logger;

    private Program()
    {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
        this._container = new CompositionContainer(catalog);
        this._container.ComposeParts(this);
    }  

Интерфейс ILogger должен получить объект Car для ведения журнала. И я не уверен, должен ли я передать это в конструкторе регистратора или как свойство, или просто как параметр метода.

  • Использование свойства : Если я использую свойство для проезда автомобиля, интерфейс ILogger выглядит следующим образом:
    public interface ILogger
    {
        Car Car { get; set; }
        void Log();
    }
    

    И я могу перебирать элементы списка, как показано ниже:
    static void Main(string[] args)
    {
        Program p = new Program(); // Composition is performed in the constructor
        var cars = new List()
            {
                new Car() { Brand = "Nissan", Model = "SkyLine" },
                new Car() { Brand = "Porche", Model = "Carrera"},
                new Car() { Brand = "Ferrari", Model = "Enzo"}
            };
        foreach (var car in cars)
        {
            p.logger.Car = car;
            p.logger.Log();
        }
        Console.ReadKey();
    }
    
  • Использование параметра : Интерфейс:

    public interface ILogger
    {
        void Log(Car car);
    }
    

    и программа:

    foreach (var car in cars)
    {
        p.logger.Log(car);
    }
    
  • Использование конструктора : Здесь я, похоже, заблудился. Я могу изменить интерфейс ILogger на:

    public interface ILogger
    {
        Car Car {get; set;}
        void Log();
    }
    

    А в реализованном классе:

    [Export(typeof(ICarLogger))]
    public class ConsoleLogger : ICarLogger
    {
        public Car Car { get; set; }
        [ImportingConstructor]
        public ConsoleLogger(Car car)
        { 
            this.Car = car;
        }
        public void Log()
        {
            Console.WriteLine("Brand: {0}\tModel: {1}", Car.Brand, Car.Model);
        }
    }
    

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

Итак, какой из этих трех подходов лучше, по вашему мнению. И как я могу реализовать подход constructor , как уже упоминалось? Надеюсь, я четко описал свою проблему.
Спасибо и извинения за длинный вопрос.
Постскриптум Я использую версию MEF, которая поставляется с .Net 4.

1 Ответ

0 голосов
/ 15 марта 2012

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

public interface ILogger
{
   void Log(IEnumerable<Car> cars);
}
...