C# 简化WCF4 RESTful服务路由的配置
“WCF REST Template 40(cs)”项目模板中的默认Global.asax.cs文件以及我在网上看到的每个教程都包含以下方法的变体:C# 简化WCF4 RESTful服务路由的配置,c#,wcf,rest,c#-4.0,C#,Wcf,Rest,C# 4.0,“WCF REST Template 40(cs)”项目模板中的默认Global.asax.cs文件以及我在网上看到的每个教程都包含以下方法的变体: private void RegisterRoutes() { // Edit the base address of Service1 by replacing the "Service1" string below RouteTable.Routes.Add(new ServiceRoute("Service1", new We
private void RegisterRoutes()
{
// Edit the base address of Service1 by replacing the "Service1" string below
RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
}
当WebApplication
本身应该能够发现哪些服务应该可用并基于约定或元数据应用路由时,以这种方式管理服务路由似乎是不必要的麻烦
问题
将我提出的解决方案转化为一个答案我想我必须假设沉默就是接受。以下是我的解决方案(源于我的问题): 假设没有更好的内置功能或其他可用功能(因为我没有找到任何功能),我尝试这样做时需要定义一个属性:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class ServiceRouteAttribute : Attribute
{
public string RoutePrefix { get; set; }
public Type ServiceFactoryType { get; set; }
public ServiceHostFactoryBase ServiceFactory
{
get
{
if (ServiceFactoryType == null || !ServiceFactoryType.IsRelated(typeof(ServiceHostFactoryBase)))
return null;
return Activator.CreateInstance(ServiceFactoryType) as ServiceHostFactoryBase;
}
}
public ServiceRouteAttribute() : this(string.empty) { }
public ServiceRouteAttribute(string routePrefix) : this(routePrefix, typeof(WebServiceHostFactory)) { }
public ServiceRouteAttribute(string routePrefix, Type serviceFactoryType)
{
RoutePrefix = routePrefix;
ServiceFactoryType = serviceFactoryType;
}
}
用于修饰应公开的每个服务合同,并将默认的注册表项更改为:
private void RegisterRoutes()
{
// `TypeHelper.GetTypes().FilterTypes<T>` will find all of the types in the
// current AppDomain that:
// - Implement T if T is an interface
// - Are decorated with T if T is an attribute
// - Are children of T if T is anything else
foreach (var type in TypeHelper.GetTypes()
.FilterTypes<ServiceRouteAttribute>())
{
// routeAttrs should never be null or empty because only types decorated
// with `ServiceRouteAttribute` should ever get here.
// `GetAttribute<T>` is my extension method for `MemberInfo` which returns all
// decorations of `type` that are T or children of T
var routeAttrs = type.GetAttributes<ServiceRouteAttribute>();
foreach (var routeAttr in routeAttrs)
{
// Some dupe and error checking
var routePrefix = routeAttr.RoutePrefix;
if (string.IsNullOrEmpty(routePrefix))
routePrefix = type.Name;
RouteTable.Routes.Add(new ServiceRoute(routePrefix,
routeAttr.ServiceFactory,
type));
}
}
}
private void RegisterRoutes()
{
//`TypeHelper.GetTypes().FilterTypes`将在
//当前AppDomain:
//-如果T是接口,则实现T
//-如果T是属性,则用T修饰
//-如果T是其他任何东西,那么T是T的孩子吗
foreach(TypeHelper.GetTypes()中的变量类型)
.FilterTypes())
{
//RouteATTR不应为null或空,因为只有类型被修饰
//带着“ServiceRouteAttribute”应该永远不会到这里。
//`GetAttribute`是我对`MemberInfo`的扩展方法,它返回所有
//属于T或T的子女的'type'装饰物
var routeAttrs=type.GetAttributes();
foreach(路由传输中的var路由传输)
{
//一些重复和错误检查
var routePrefix=routeAttr.routePrefix;
if(string.IsNullOrEmpty(routePrefix))
routePrefix=type.Name;
RouteTable.Routes.Add(新服务路由(routePrefix,
routeAttr.ServiceFactory,
类型);
}
}
}
这似乎是可行的,也不太麻烦,因为它只发生在应用程序启动时
,但我对使用WCF4构建RESTful web服务还不熟悉,所以我不知道它会导致什么样的问题
如果有人想出一个更优雅的方法来解决这个问题,我很乐意考虑其他的选择。