2016-08-25 4 views
3

내가 같은 일반적인 ASP.NET 코어 WebApi 컨트롤러가 있습니다제네릭 형식 인수를 사용하여 ProducesResponseType을 사용하기 위해 특성에서 형식 매개 변수를 사용하기위한 해결 방법은 무엇입니까?

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 콘크리트 유형 만 사용하십시오. ? 인 ApplicationModel을 업데이트

사용 IApplicationModelConvention : :-(

더 나은 작업 방법 내가 ProducesResponseTypeAttribute에서 제네릭 형식 매개 변수를 사용하는 방법을 찾을 수 없습니다 Althrough

+0

제가 생각할 수있는 유일한 이유는 런타임에 제네릭 형식 매개 변수가 해결된다는 것입니다. 그러나 속성 매개 변수는 컴파일시 해결되어야합니다. 따라서 일반 유형 매개 변수를 속성에 대한 인수로 사용할 수 없습니다. 당신이 볼 수 있습니다 [여기] (https://msdn.microsoft.com/en-us/library/t9h2ax10.aspx) 및 [여기에 (http://stackoverflow.com/questions/294216/why-does- c-sharp-forbid-generic 속성 유형). 해결 방법은 가능한 경우 푸시하려고합니다. –

답변

2

, 나는 자신감 작업 할 수있는 또 다른 방법을 발견 자신감에서 사용

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 인스턴스를 추가하면 자신감이는 자신감이나 버그의 수 있으며, 제대로 작동하지 않습니다 asp.net 핵심. 그래서 ProducesResponseStub을 사용하여 EntityController에 작업 방법을 꾸미고 EntityControllerConversion에 올바른 유형으로 바꿉니다.

관련 문제