1

Я работаю над добавлением контейнера Windsor IoC в существующее приложение WinForms, которое использует шаблон дизайна MVP UI. Я пытаюсь определить хороший подход к повторной загрузке datacontext, который зависит от строки подключения, предоставленной во время выполнения. Проблема в том, что я не могу создать datacontext, пока пользователь не выберет базу данных, то есть «строку соединения» после загрузки приложения. Предполагается, что обычно используется только один datacontext, но иногда пользователю необходимо переключиться на другую базу данных, т. Е. Создать файл данных differnet datacontext. Это также приводит к дополнительным зависимостям времени выполнения.Runtime datacontext with Castle Windsor

public interface IProductsView 
{ 
    event EventHandler<ProductSelectedEventArgs> ProductSelectedEvent; 
    event EventHandler<StringEventArgs> ProductStatusEvent; 
    void ClearProductList(); 
    void DisplayProductList(IList<Product> products); 
    Control Control { get; } 
    IProductsPresenter Presenter { get; set; } 
} 

public class ProductsPresenter : IProductsPresenter 
{ 
    public IProductsView View { get; set; } 
    private IProductRepository Repository { get; set; } 

    public ProductsPresenter(IProductsView view, IProductRepository repository) 
    { 
     View = view; 
     View.Presenter = this; 
     Repository = repository; 
    } 

    public void ProductSelected(IList<Product> products) 
    { 
     throw new NotImplementedException(); 
    } 

    public void ShowProductList(string name) 
    { 
     IList<Product> productList; 

     if (string.IsNullOrEmpty(name)) 
      productList = Repository.GetProducts(); 
     else 
      productList = Repository.GetProductsByName(name); 

     View.DisplayProductList(productList); 
    } 
} 

public class ProductDao : IDisposable, IProductRepository 
{ 
    private MeasurementDataContext dataContext; 

    public ProductDao(MeasurementDataContext context) 
    { 
     dataContext = context; 
    } 

    public List<Product> GetProducts() 
    { 
     return dataContext.Products.Select(p => Mapper.Map(p)).ToList().OrderBy(x => x.Name).ToList(); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
      if (dataContext != null) 
      { 
       dataContext.Dispose(); 
       dataContext = null; 
      } 
    } 

    ~ProductDao() 
    { 
     this.Dispose(false); 
    } 
} 

Таким образом, это означает, что Presenter в моем View равно нулю, пока IProductRepository не создается, что, в свою очередь, зависит от создания MeasurementDataContext. У меня есть эти компоненты Regisitered в IWindsorInstaller как так:

container.Register(Component.For<IProductsView>() 
      .ImplementedBy<ViewProductsControl>()); 
     container.Register(Component.For<IProductsPresenter>() 
      .ImplementedBy<ProductsPresenter>()); 

мне нужно использовать Named и DependsOn, которые поставляют уникальное имя и ConnectionString аргумент для каждого DataContext ли?

Что я в настоящее время сделать, чтобы зарегистрировать контекст данных во время выполнения после того, как пользователь выбрал базу данных

kernel.Register(Component.For<MeasurementDataContext>() 
       .UsingFactoryMethod(() => new MeasurementDataContext(conn))); 

и затем `Resolve» мои взгляды и установить их ведущих. Я знаю, что это не хороший дизайн, но это грубый способ решения моих проблем.

Благодаря

UPDATE:

Я изменил то, как я зарегистрировал свой DataContext-х в инсталлятор на следующее:

container.Register(Component.For<DataContext>().ImplementedBy<MeasurementDataContext>().Named("Localhost").DependsOn(new { connectionString = conn })); 

, а затем модифицирован конструктор моей модели, чтобы:

public ProductDao(DataContext context) 
    { 
     dataContext = context as MeasurementDataContext; 
    } 

Все компоненты будут решить с правой клавиши:

kernel.Resolve<DataContext>(cbo.SelectedItem.ToString()); 
+0

Не связано с вашими вопросами, но нет причин для внедрения полнофункциональной версии финализатора шаблона Dispose, поскольку вы используете только управляемые ресурсы. Если ваш финализатор выполнит это, он ничего не сделает (diposing = false в вашем методе Dispose() ничего не дает); это просто лишний штраф за исполнение. – roken

ответ

1

насчет инъекционного класса-оболочки для хранения строки подключения и иметь DataContext объекты использовать это? Что-то в этих строках:

public class ConnectionStringProvider : IConnectionStringProvider 
{ 
    private string _value; 

    public event EventHandler ConnectionStringChanged; 

    public string ConnectionString 
    { 
     get { return _value; } 
     set 
     { 
      _value = value; 

      var del = ValueChanged; 
      if (del != null) 
       del(this, EventArgs.Empty); 
     } 
    } 
} 

Зарегистрируйте это с помощью образа жизни одного человека. Таким образом ваше приложение может установить или обновить строку соединения на одном объекте, и все, кто от этого зависит, будут уведомлены об этом изменении.

+0

Спасибо за предложение! Я закончил изменять, как я регистрирую datacontexts в установщике, как показано в моем отредактированном сообщении выше. –

+0

Я не уверен, как зарегистрировать свой файл datacontext, так что это зависит от класса-оболочки. У вас есть пример? –

Смежные вопросы