【问题标题】:Generic Web Api method通用 Web Api 方法
【发布时间】:2015-06-06 12:57:17
【问题描述】:

我有一些像 CustomerModelCustomerDetailsModel 这样的类继承自 ModelBase

我也不想为每个模型类型引入子类。

在一种情况下,foreach 有一个 post 方法。

所以我可以手动创建多个路由来调用一个看起来像这样的方法

Handle<T>(T model) where T : ModelBase

它们仅在被调用的路径上有所不同。例如:

baseurl/api/customer => CustomerModel
baseurl/api/customerdetails => CustomerDetailsModel

我想实现一个通用的 web api 方法,比如

[HttpPost]
void Post<T>(T model) where T : ModelBase

如果我只是创建一个泛型方法,我会得到一个异常,它告诉我 web api 方法不能有泛型方法。但是前段时间我看到了一个使用 web api v1 的实现,它使用某种自定义查找机制来处理这个问题。但是我想不通了。

作为一种解决方法,我创建了一个调用包装器,它确定类型并调用内部泛型方法,但这感觉很丑

 public async Task<IHttpActionResult> Post(string id, string moduleType)
        {
            await AsyncGenericCallWrapper(moduleType);
...

如果有上面提到的通用控制器,那就太好了。

  private async Task AsyncGenericCallWrapper(string moduleType)
        {
            Type type = GetModuleType(moduleType);
            var content = await Request.Content.ReadAsStringAsync();
            var instance = JsonConvert.DeserializeObject(content, type);

            MethodInfo method = this.GetType().GetMethod("InternalGenericMethod", BindingFlags.NonPublic | BindingFlags.Instance);
            MethodInfo generic = method.MakeGenericMethod(type);
            var result = generic.Invoke(this, new object[] { instance }) as Task;

            await result;
        }

我可以图像有一个自定义属性来映射类型,如

[GenericRoute("/customer", typeof(CustomerModel)]
[GenericRoute("/customerDetail", typeof(CustomerDetailModel)]
void Post<T>(T model) where T : ModelBase

有了这个我可以为每个属性创建路由,但现在仍然调用该方法,因为它是通用的,我也不知道如何干扰反序列化机制

谁能告诉我如何实现那个 GenericWebAPiMethod?

【问题讨论】:

  • These answers 似乎表明它可能可能,但它使事情变得比子类化更复杂。
  • 我知道,但是在我的场景中,拥有子类并没有帮助。因为我想让它动态扩展而不重新部署网页。在运行时新模型是可能的

标签: c# generics asp.net-web-api asp.net-web-api2 asp.net-web-api-routing


【解决方案1】:

这种方法的问题是 Web API 不知道如何反序列化对象。

您可以创建一个通用控制器,而不是使用通用方法。

假设你的模型是这样的:

public abstract class ModelBase{ }

public class CustomerModel : ModelBase {}

public class CustomerDetailsModel: ModelBase { }

您可以编写一个通用控制器来处理从 ModelBase 继承的类:

public class ModelBaseController<T> : ApiController where T : ModelBase 
{
    [HttpPost]
    public void Post(T model)
    {
        ...
    }
}

public class CustomerModelController : ModelBaseController<CustomerModel>
{
}

public class CustomerDetailsModelController : ModelBaseController<CustomerDetailsModel>
{
}

【讨论】:

  • 看准了!谢谢
  • 为了获得更多乐趣,您还可以使用mvcBuilder.ConfigureApplicationPartManager 并更直接地使用您的ModelBaseController&lt;T&gt;
猜你喜欢
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 2019-05-05
相关资源
最近更新 更多