3

インターフェイスとそれを実装IRDFReportする基本クラスがあります。BaseReportおよびプロパティは重いオブジェクトであり、レポートが実際に要求されている場合にのみ解決する必要がありますViewReportオブジェクトの名前付きマッピングViewReportプロパティを見つけるために、2 つの単純な文字列サフィックスを使用しました。

Unity を使用して重いオブジェクトをオンデマンドで解決し、すべてのレポートを解決してそれらのリストを取得できるようにしたいと考えています。この種のgetメソッドでの解決は、これに対して私ができる最善のことですか?

public interface IRDFReport
{
    UserControl View { get; }
    string ReportName { get; }
    string Name { get; set; }
    Task<bool> GenerateReport(SynchronizationContext context);
    DevExpress.XtraReports.IReport Report { get; set; }
}

BaseReportこのインターフェースを実装します:

public class BaseReport : IRDFReport
{

    public DevX.IReport Report
    {
        get
        {
            return ReportManager.myContainer.Resolve<IReport>(ReportName + ReportManager.Report_Suffix) as XtraReport;
        }
    }

    public UserControl View
    {
        get
        {
            return ReportManager.myContainer.Resolve<UserControl>(ReportName + ReportManager.View_Suffix);
        }
    }

    ///
    /// other members
    ///
}       

そして、私のレポート マネージャーでは、次のように登録します。

public const string View_Suffix = ".View";
public const string Report_Suffix = ".XtraReport";

Reports = new List<IRDFReport>();

myContainer.RegisterType<IReport, BalanceSheetXtraReport>(nameof(BalanceSheetReport) + Report_Suffix, new ContainerControlledLifetimeManager());
myContainer.RegisterType<UserControl, BalanceSheetView>(nameof(BalanceSheetReport) + View_Suffix, new ContainerControlledLifetimeManager());

  ///
  /// registering other reports inherited from BaseReport
  ///

myContainer.RegisterTypes(
    AllClasses.FromLoadedAssemblies()
    .Where(type => typeof(IRDFReport).IsAssignableFrom(type)),
    WithMappings.FromAllInterfaces,
    WithName.TypeName);

var reports = myContainer.ResolveAll<IRDFReport>().Where(x => !string.IsNullOrEmpty(x.Name)).ToList();
Reports.AddRange(reports);
4

1 に答える 1

3

あなたがしていることは Service Location と呼ばれ、アンチパターンと見なされます

依存関係を取得する別の方法を提案します。例として、いくつかの一般的なコードを提供することに注意してください。また、私はIReportのみについて話します。他の依存関係も同様に扱うことができます。

私が提案しているのは、コンストラクター インジェクションを使用することです。あなたBaseReportは に依存していIReportますが、必要に応じて後で取得 (および構築) できるようにしたいと考えています。

これを行う 1 つの方法は、抽象ファクトリを使用することです。

次に例を示します。

public interface IReportFactory
{
    IReport Create(); //this can also take parameters
}

次に、このファクトリの実装を作成し、それを のコンストラクタに注入できますBaseReport。これにより、オンデマンドで依存関係BaseReportをリクエストできるようになります。IReport

もう 1 つの解決策は、.NET Lazyクラスを使用することです。このクラスを使用すると、初めて使用するときに依存関係を作成できます。LazyUnity には、クラスのネイティブ サポートがあります (このリファレンスを参照してください)。

使用方法の例を次に示します。

次のようにクラスに注入できLazy<IReport>ます。BaseReport

public class BaseReport
{
    private readonly Lazy<IReport> m_LazyReport;

    public BaseReport(Lazy<IReport> lazy_report)
    {
        m_LazyReport = lazy_report;
    }

    public IReport Report
    {
        get { return m_LazyReport.Value; }
    }
}

コンポジション ルート(DI コンテナーを使用する場所) で、次の操作を行います。

UnityContainer container = new UnityContainer();

container.RegisterType<IReport, Report>("name");

container.RegisterType<BaseReport>(
    new InjectionConstructor(
        new ResolvedParameter<Lazy<IReport>>("name")));

を登録するだけで十分です。そうすればIReport、Unity は問題Lazy<IReport>なく解決できます。また、Lazyオブジェクトの値にアクセスした場合にのみ先に進み、Reportオブジェクトを作成するように動作させることを認識しています。

于 2015-10-17T21:24:18.107 に答える