[英]C# - Doesn't allow me to return “this” as a type when interface for type is implemented
[英]C# function to return the implemented interface of a type
我有一個單例工廠類示例,在該示例中,我使用了字典並在運行時確定相關的報告類..因為每個報告服務還必須執行40種組合。
public sealed class ReportServiceFactory : IGetReportServices
{
private static readonly ReportServiceFactory instance = new ReportServiceFactory();
private static readonly Dictionary<Tuple<ReportTypes, ReportPeriodTypes>, IServiceReports> reportEntityServices =
new Dictionary<Tuple<ReportTypes, ReportPeriodTypes>, IServiceReports> {
{ Tuple.Create(ReportTypes.Foo, ReportPeriodTypes.Week), new FooService<FooWeekEntity>() },
{ Tuple.Create(ReportTypes.Foo, ReportPeriodTypes.Month), new FooService<FooMonthEntity>() },
{ Tuple.Create(ReportTypes.Bar, ReportPeriodTypes.Week), new BarService<BarWeekEntity>() },
{ Tuple.Create(ReportTypes.Bar, ReportPeriodTypes.Month), new BarService<BarMonthEntity>() }
};
// Explicit static constructor to tell C# compiler not to mark type as beforefieldinit
static ReportServiceFactory()
{
}
private ReportServiceFactory()
{
}
public static ReportServiceFactory Instance
{
get { return instance; }
}
public IServiceReports Get(ReportTypes reportType, ReportPeriodTypes periodType)
{
if (!Enum.IsDefined(typeof(ReportTypes), reportType))
throw new ArgumentOutOfRangeException("reportType");
if (!Enum.IsDefined(typeof(ReportPeriodTypes), periodType))
throw new ArgumentOutOfRangeException("periodType");
var reportTuple = Tuple.Create(reportType, periodType);
if (!reportEntityServices.ContainsKey(reportTuple))
return null;
return reportEntityServices[reportTuple];
}
}
我希望能夠為工廠中的Get()
函數返回一個更特定的接口,以在執行時將其更改為IServiceFooReports
為例作為示例...這樣,我可以訪問下面的FooViewModel
Get()
函數而無需將結果轉換為其他調用代碼。
public interface IServiceFooReports : IServiceReports
{
IEnumerable<FooViewModel> Get();
}
public class FooService<T> : IServiceFooReports
{
... use EF model context and call .CreateObjectContext<T>()
do filtering on the IQueryable result and return the result materialised as the relevant view models
}
這可能嗎? 如果需要更改,這里是IGetReportServices
接口。 IServiceReports
為空,目前僅用作將這些報表服務存儲在同一詞典中的方式...標記界面?
public interface IGetReportServices
{
IServiceReports Get(ReportTypes reportType, ReportPeriodTypes reportPeriodType);
}
如果希望以IGetReportServices界面強制轉換的對象返回IServiceFooReports而不強制轉換,則可以在接口上添加一個為您進行強制轉換的方法。 如果將服務實例強制轉換為接口,則定義“新”方法來更改返回類型的任何技巧都不會返回更具體的類型。
IServiceReports GetFoo(..., ...);
用類似的實現
public IServiceFooReports GetFoo(ReportTypes reportType, ReportPeriodTypes reportPeriodType){
return this.Get(reportType, reportPeriodType) As IServiceFooReports;
}
或者,您可以使用通用方法,例如
T Get<T>(ReportTypes reportType, ReportPeriodTypes reportPeriodType);
但是然后您需要知道類的類型才能調用該方法,因此它真的比之后必須強制轉換結果更好。 另一方面,如果可以將報表邏輯設計為使用報表類型而不是ReportTypes枚舉,則可以利用隱式強制轉換。
List<T> Get<T>(T reportTemplate, ReportPeriodTypes reportPeriodType);
然后,您可以像下面這樣調用方法:
var template = new FooViewModel();
List<FooViewModel> results = Get(template, reportPeriodType);
不確定是否有幫助
當然。 接口可以繼承其他接口。 完成后,可以使用多態在它們表示的類型之間進行轉換,就像使用類繼承一樣。 作為一個簡單的示例,如果您具有以下接口:
public interface IFoo
{
string Get();
}
public interface IBar : IFoo
{
new string Get();
}
和以下類:
public class MyClass : IBar
{
public string Get()
{
return @"some data";
}
}
那么您可以實現以下方法:
public MyClass SomeMethod()
{
MyClass myVariable = new MyClass();
return myVariable;
}
並調用該方法以填充由接口定義的類型的變量,該接口不是由MyClass明確實現的,而是由MyClass 確實實現的接口定義的。 即
IFoo myOtherVariable = SomeMethod() as IFoo;
注意:關鍵是MyClass沒有顯式實現“ IFoo”。 它僅實現“ IBar”,后者繼而繼承“ IFoo”。
因此,將以上信息應用於您的問題,假設您的接口IServiceFooReports 實現了 IServiceReports,並且提供了方法的內部工作,則創建了類型為“ IServiceFooReports”的對象,則可以通過類型“ IServiceReports”返回該對象。 在方法之外,您應該能夠使用“ as”關鍵字將輸出安全地轉換為更特定的類型“ IServiceFooReports”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.