2012-12-19 26 views
9

parametreleri. Benim düşüncem tüm istekler için arayüzler oluşturmak ve sadece bu arayüzleri Web API kodunda kullanmaktı.Bağımlılık enjeksiyon ben mobil bir uygulamanın bir JSON arabirimi için C# bir ASP.NET Web API proje üzerinde çalışıyorum

public interface IApiObject {} 
public interface IApiResponse<T> : IApiObject where T : IApiObject {} 
public interface IApiRegistrationRequest : IApiObject {} 

Benim denetleyicisi şuna benzer::

public class MyApiController : ApiController 
{ 

    public IApiResponse<IApiObject> Register(IApiRegistrationRequest request) { 
     // do some stuff 
    } 
} 

My Web API Proje ayrıca bu ara yüzlerin uygulamaları içermektedir

böyle bir şey ile sona erdi.

Web API projelerinin MVC projeleri gibi model ciltleme kullandığını farz ettim, böylece tüm IApiObject'ler için bir bağlayıcı ve uygulamaları için arabirimleri çözmek için bir Unity konteyner kullanarak özel bir model bağlayıcı sağlamak üzere bir inheritance aware ModelBinderProvider oluşturdum.

Ancak, bazı daha soruşturma sonrasında, ben How Web API does parameter binding geldi ve Web API yerine karmaşık türleri için örnek bağlayıcıların biçemleyicileri kullanır öğrendim. Bağlantılı blog yayını, işlem parametrelerimde ModelBinderAttribute kullanılmasını önerir, ancak bu özellik yalnızca bir parametre olarak bir türü kabul eder. Benim özel model bağlayıcı Ancak boş bir yapıcı (bir birlik kabı ihtiyacı) içermez, bu yüzden bunun bir örneğini geçmesi gerekir. Aklıma

başka yolu formatlayıcılar için bağımlılık enjeksiyon kullanıyor. Ne yazık ki, onları daha önce hiç kullanmadığım için yabancı değilim.

gitmek için doğru yol hangisi? Ve ben nasıl yaparım?

cevap

5

servis yığını üzerinde inanılmaz serisi Şu ana ile geldi ve çalışıyor budur yoktur.

Ben birlik çağrıları ve ileriye çözülmesi türünü kullanarak başka biçimlendiriciye diğer tüm operasyonlar yapan bir özel biçemleyici kurmaya karar verdik. Çok fazla kod gibi görünüyor, ancak bunun nedeni sadece tüm yöntemlerin üzerine yazılması gerektiğinden, tür her zaman çözülebilir.

public class UnityFormatter : MediaTypeFormatter 
{ 
    private MediaTypeFormatter formatter; 

    private IUnityContainer container; 

    public UnityFormatter(MediaTypeFormatter formatter, IUnityContainer container) 
    { 
     this.formatter = formatter; 
     this.container = container; 

     foreach (var supportedMediaType in this.formatter.SupportedMediaTypes) 
     { 
      this.SupportedMediaTypes.Add(supportedMediaType); 
     } 

     foreach (var supportedEncoding in this.formatter.SupportedEncodings) 
     { 
      this.SupportedEncodings.Add(supportedEncoding); 
     } 

     foreach (var mediaTypeMapping in this.MediaTypeMappings) 
     { 
      this.MediaTypeMappings.Add(mediaTypeMapping); 
     } 

     this.RequiredMemberSelector = this.formatter.RequiredMemberSelector; 
    } 

    private Type ResolveType(Type type) 
    { 
     return this.container.Registrations.Where(n => n.RegisteredType == type).Select(n => n.MappedToType).FirstOrDefault() ?? type; 
    } 

    public override bool CanReadType(Type type) 
    { 
     return this.formatter.CanReadType(this.ResolveType(type)); 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return this.formatter.CanWriteType(this.ResolveType(type)); 
    } 

    public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) 
    { 
     return this.formatter.GetPerRequestFormatterInstance(this.ResolveType(type), request, mediaType); 
    } 

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
    { 
     return this.formatter.ReadFromStreamAsync(this.ResolveType(type), readStream, content, formatterLogger); 
    } 

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) 
    { 
     this.formatter.SetDefaultContentHeaders(this.ResolveType(type), headers, mediaType); 
    } 

    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) 
    { 
     return this.formatter.WriteToStreamAsync(this.ResolveType(type), value, writeStream, content, transportContext); 
    } 
} 

Son olarak, özel biçimlendiricimizi uygulama yapılandırmasına kaydedin (Global.asax Application_Start). Tüm geçerli formatları benim özel örneğimle değiştirmeyi seçtim, böylece tüm veri türleri için yansıma elde ediyorum.

// set up unity container, register all types 
UnityContainer container = new UnityContainer(); 
container.RegisterType<IApiRegistrationRequest, ApiRegistrationRequest>(); 

// save existing formatters and remove them from the config 
List<MediaTypeFormatter> formatters = new List<MediaTypeFormatter>(GlobalConfiguration.Configuration.Formatters); 
GlobalConfiguration.Configuration.Formatters.Clear(); 

// create an instance of our custom formatter for each existing formatter 
foreach (MediaTypeFormatter formatter in formatters) 
{ 
    GlobalConfiguration.Configuration.Formatters.Add(new UnityFormatter(formatter, container)); 
} 
İlgili konular