繁体   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