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