我有一个接口IRDFReport
和一个实现它的基类BaseReport
。 View
和Report
属性是重型对象,只有在实际请求报告时才应解析。我使用了两个简单的字符串后缀来查找对象的View
和Report
属性的命名映射。
我想使用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);
答案 0 :(得分:3)
您正在做的事情称为服务地点和is considered an anti-pattern。
我将建议一种获得依赖关系的不同方法。请注意,我将提供一些通用代码作为示例。而且我也只会谈论IReport
。可以类似地对待其他依赖。
我建议使用构造函数注入。您的BaseReport
依赖于IReport
,但它希望能够仅在以后按需获取(并构建它)。
执行此操作的一种方法是使用abstract factory。
以下是一些例子:
public interface IReportFactory
{
IReport Create(); //this can also take parameters
}
然后,您可以创建此工厂的实现并将其注入BaseReport
的构造函数。这将使BaseReport
能够根据需求请求IReport
依赖。
另一种解决方案是使用.NET Lazy类。此类允许您在第一次尝试使用它时创建依赖项。 Unity对Lazy
类提供本机支持(请参阅this reference)。
以下是如何使用它的示例:
您可以将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; }
}
}
在Composition Root(您使用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
对象。