1

MVP UI デザイン パターンを使用する既存の WinForms アプリケーションに Windsor IoC コンテナーを追加する作業を行っています。実行時に提供される接続文字列に依存するデータコンテキストを登録するための適切なアプローチを決定しようとしています。問題は、アプリケーションがロードされた後、ユーザーがデータベース、つまり「接続文字列」を選択するまで、データコンテキストを作成できないことです。通常は 1 つのデータコンテキストのみが使用されますが、ユーザーが別のデータベースに切り替える必要がある場合があります。つまり、別のデータコンテキストを作成する場合です。これにより、追加のランタイム依存関係も発生します。

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);
    }
}

したがって、これは、 が作成されるまでPresentermy 内のViewが nullであることを意味します。これは、 のIProductRepository作成に依存しMeasurementDataContextます。私はこれらのコンポーネントを次のIWindsorInstallerように登録しています:

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

各データコンテキストに一意の名前と connectionString 引数を指定する必要がありNamedますか?DependsOn

ユーザーがデータベースを選択した後、実行時にデータコンテキストを登録するために現在行っていること

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

次に、ビューを「解決」してプレゼンターを設定します。これが良い設計ではないことはわかっていますが、依存関係を解決するための強引な方法です。

ありがとう

アップデート:

インストーラーにデータコンテキストを登録する方法を次のように変更しました。

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());
4

1 に答える 1

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);
        }
    }
}

これをシングルトン ライフスタイルに登録します。このようにして、アプリケーションは単一のオブジェクトの接続文字列を設定または更新でき、それに依存するすべての人に変更が通知されます。

于 2012-05-29T14:42:27.180 に答える