簡體   English   中英

C#函數返回類型的已實現接口

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM