簡體   English   中英

在多個名稱空間中可用的相同擴展類

[英]Same extension class available in multiple namespaces

在MVC應用程序中,我有一個包含特定模型類的名稱空間。 此類實現特定的接口,並且所述接口具有擴展類。

我將擴展類放在與模型類和接口相同的名稱空間中,但是,除非將名稱空間公開在視圖中,否則擴展方法在視圖中將不起作用。 通過在實際上將要使用這些擴展方法的每個視圖中using添加名稱空間不是一種選擇。 幸運的是, 我知道如何全局添加一個名稱空間,以便可以在所有視圖中使用它 ,但是我有理由不向其公開我的模型名稱空間。

考慮到這一點,我正在考慮將擴展方法移動到其他名稱空間,以便可以將其安全地公開給所有視圖,但是現在所有有權訪問模型名稱空間的控制器都將缺少擴展。 我不想將此命名空間添加到我的所有控制器中,這一次,我不想使此命名空間全局可用。 我確實希望擴展僅在模型名稱空間公開的代碼中可用。

便宜的解決方案是將相同的擴展類添加到兩個名稱空間(換句話說,兩個具有完全相同代碼的cs文件)並使用它來完成,但是我想盡可能使用更好的解決方案。

有一陣子我以為我可以在另一個命名空間中繼承擴展類,但這不能工作,因為靜態類不能繼承任何東西。

我也嘗試使用解決方案,但它不起作用(至少對於擴展類而言)。 我的意思是我公開了僅包含視圖擴展的名稱空間,但是視圖中的對象無法訪問擴展方法。 我還必須向名稱空間添加一個虛擬類(否則應用程序甚至不會注意到名稱空間)。

總結起來,我有一個擴展類,需要在兩個不同的命名空間中使用它。 除了將上述類復制粘貼到其他名稱空間之外,還有其他方法可以實現嗎?

當然,您不能在兩個名稱空間中使用相同的類 ,但是可以使用相同的代碼生成兩個類。

一種方法是使用T4生成一個同時包含兩個類的文件。 (您可能不熟悉T4。如果使用Entity Framework,即使您不知道它,也可以將它包含在項目中。)

使用命名空間上的foreach將文本模板(.tt)文件添加到您的項目中,如下所示:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>

using System;
using System.Collections.Generic;
using System.Globalization;

<#
    foreach (var @namespace in new [] { "One.Two", "First.Second" }) 
    {
#>
namespace <#= @namespace #>
{
    public static class UsefulExtensions
    {
        public static IEnumerable<String> ToTextElements(this String str)
        {
            var iter = StringInfo.GetTextElementEnumerator(str);
            while (iter.MoveNext()) 
            {
                yield return iter.GetTextElement();
            }           
        }
    }
}

<#
    }
#>

或者,可以通過將擴展名更改為.tt並將CustomTool屬性設置為TextTemplatingFileGenerator並將Build Action屬性設置為None來轉換.cs文件。

您可以做的一件事是在主名稱空間中定義擴展方法:

namespace MyNamespace
{
    public interface ISomeInterface { }

    public static class SomeInterfaceExtensions
    {
        public static string DoSomething(this ISomeInterface someObject)
        {
            //Do something

            return "I did something";
        }
    }
}

然后,在要公開給視圖或控制器的名稱空間中,可以使用一個瘦擴展進行包裝,該擴展將一直傳遞到主要的擴展:

using MyNamespace;

namespace ViewAccessibleNamespace
{
    public static class SomeInterfaceExtensions
    {
        public static string DoSomethingWrapper(this ISomeInterface someObject)
        {
            return someObject.DoSomething();
        }
    }
}

和:

using MyNamespace;

namespace ControllerAccessibleNamespace
{
    public static class SomeInterfaceExtensions
    {
        public static string DoSomethingWrapper(this ISomeInterface someObject)
        {
            return someObject.DoSomething();
        }
    }
}

這確實需要為包裝方法指定與主要方法不同的名稱,但是它利用了核心擴展代碼而不必重復它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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