2016-08-25 5 views
3

私のような一般的なASP.NETコアWEBAPIコントローラがあります。ProducesResponseTypeをジェネリック型引数で使用するための属性でtypeパラメータを使用する場合の回避策はありますか?

public abstract class EntityController<TEntity> 
{ 
    public IActionResult Get(string id) 
    { 
     var entity = ... //load from database by id 
     if (entity != null) 
      return new JsonResult(value, this.SerializerSettings()) {StatusCode 200}; 
     return NotFound(); 
    } 
} 

を、私はGet()法上の次の属性適用したい:今のところ

[ProducesResponseType(typeof(TEntity), 200)] //this causes compilation error. 
[ProducesResponseType(typeof(Object), 404)] 

を、周りの唯一の仕事は、上書きすることです派生したコントローラの各メソッドを追加し、そこに属性を追加してください:

public class DerivedController :EntityController<MyEntity> 
{ 
    [ProducesResponseType(typeof(TEntity), (int) HttpStatusCode.OK)] 
    [ProducesResponseType(typeof(Object), (int) HttpStatusCode.NotFound)] 
    public IActionResult Get(string id) 
    { 
     return base.Get(id); 
    } 
} 

私はオーバーライドする必要が非常に不便ですすべてのコントローラ内のすべてのRESTメソッドを使用して、コンクリートのTEntityコンクリートを使用します。 ?:-(

任意のより良い回避策

+0

私が考えることができる唯一の理由は、ジェネリック型のパラメータが実行時に解決されるということです。しかし、属性パラメータはコンパイル時に解決されなければなりません。したがって、属性の引数としてジェネリック型のパラメータを使用することはできません。あなたは見た目[ここ](https://msdn.microsoft.com/en-us/library/t9h2ax10.aspx)と[ここ](http://stackoverflow.com/questions/294216/why-does- c-sharp-forbid-generic-attribute-types)を参照してください。回避策のために、できるならば何かを押してみようと思います。 –

答えて

2

私はProducesResponseTypeAttributeでジェネリック型パラメータを使用する方法を発見したAlthrough、私が闊歩の仕事を作るために別の方法を見つけました:

使用IApplicationModelConventionApplicationModelを更新するために、あります闊歩で使用

public class EntityControllerConversion : IApplicationModelConvention 
{ 
    public void Apply(ApplicationModel application) 
    { 
     ActionModel action = ... // finds the controller action 
     Type viewModelType = ... // get the view type by reflection from the controller 
     SetResponseUsingHack(action, viewModelType, HttpStatusCode.OK); 
    } 

    private void SetResponseUsingHack(ActionModel actionModel, Type responseType, HttpStatusCode statusCode) 
    { 
     if (actionModel == null) throw new ArgumentNullException(nameof(actionModel)); 
     if (responseType == null) throw new ArgumentNullException(nameof(responseType)); 

     var writable = (IList<object>)(actionModel.Attributes); 
     var attribute = FindResponseAttributeUsingHack(writable, statusCode); 
     if (attribute != null) 
     { 
      attribute.Type = responseType; 
     } 
    } 

    private ProducesResponseTypeAttribute FindResponseAttributeUsingHack(IList<object> attributes, HttpStatusCode statusCode) 
    { 
     if (attributes == null) return null; 
     var result = attributes.OfType<ProducesResponseTypeAttribute>() 
      .Where(x => x.Type == typeof(ProducesResponseStub)) 
      .FirstOrDefault(x => x.StatusCode == (int) statusCode); 
     return result; 
    } 
} 

public abstract class EntityController<TEntity> 
{ 
    [HttpGet] 
    [ProducesResponseType(typeof(ProducesResponseStub), 200)] 
    public IActionResult Get(string id) 
    { 
    } 
} 

public static class ProducesResponseStub 
{ 
} 

注:あなただけActionModel.Attributesに新しいProducesResponseTypeAttributeインスタンスを追加する場合SWAGGERはそれが闊歩またはのバグだとすることができ、正常に動作しませんasp.netコア。そのため私はを使用してEntityControllerのアクションメソッドを装飾し、正しいタイプをEntityControllerConversionに置き換えました。

関連する問題