排除 ODataConventionModelBuilder 中实现的接口

本文关键字:接口 实现 ODataConventionModelBuilder 排除 | 更新日期: 2023-09-27 18:36:29

我在使用 Web API 2 和 OData v3 时遇到了一个奇怪的问题,特别是ODataConventionModelBuilder。我的WebApiConfig.cs中有以下代码:

// Web API configuration and services
var builder = new ODataConventionModelBuilder();
// Adding all the entity sets here, then complex types, custom actions, ...
builder.EntitySet<Address>("Addresses");
/* ... */
builder.AddComplexType(typeof(CustomerSearchResultDto));
/* ... */
var customerSearchAction = builder.Entity<Customer>().Collection.Action("Search");
        patientSearchAction.Parameter<string>("pattern");
        patientSearchAction.Parameter<bool>("searchDeactivated");
// These are the interfaces that some entities implement. These MUST NOT be put into the model
var interfaces = typeof(ICustomer).Assembly.GetTypes().Where(t => t.IsInterface).ToArray();
builder.Ignore(interfaces);
// Building models
var model = builder.GetEdmModel();
config.Routes.MapODataServiceRoute("odata", "odata", model);

模型构建良好,无一例外。但是某些实体实现的接口被转换为复杂类型,这当然是荒谬的,并且在客户端会导致相当多的命名空间混乱。以下是生成的元数据的摘录(服务:1111/$metadata)

<ComplexType Name="IAddress">
    <Property Name="Street1" Type="Edm.String" />
    <Property Name="Street2" Type="Edm.String" />
    <Property Name="Zip" Type="Edm.String" />
    <Property Name="City" Type="Edm.String" />
    <Property Name="Country" Type="Edm.String" />
</ComplexType>

我也尝试使用builder.Ignore<IAddress>,但无济于事。我做错了什么?

排除 ODataConventionModelBuilder 中实现的接口

我找到了更好的解决方案。在WebApiConfig中.cs我为每个实体执行:

builder.EntitySet<Address>("Addresses").EntityType.DerivesFromNothing();

如果实体派生自另一个实体,我使用 DerivesFrom() 方法。为了避免命名空间与我的复杂类型发生冲突,我使用 DTO。由于我有很多,所以我只是像这样批量添加它们(使用反射):

var builderMethod = builder.GetType().GetMethod("ComplexType");
foreach (var type in typeof (WebApiConfig).Assembly.GetTypes().Where(x => x.Name.EndsWith("Dto")))
{
    var genericMethod = builderMethod.MakeGenericMethod(type);
    genericMethod.Invoke(builder, null);
}

这很有效。

我想你有一个定义为IAddress的属性,例如:

public class Customer
{
    public int CustomerId { get; set; }
    public IAddress Address { get; set; }
    ...
}

因此,builder.Ignore(interfaces);不起作用。

如果是这样,您可以:

  1. 更改模型定义,使用抽象类,而不是使用接口。
  2. 或者,尝试Ignore该属性。