9

モバイルアプリケーションへのJSONインターフェイス用にC#でASP.NETWebAPIプロジェクトに取り組んでいます。私のアイデアは、すべてのリクエストのインターフェイスを作成し、WebAPIコードでこれらのインターフェイスのみを使用することでした。

私は次のようなものになりました:

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

私のコントローラーは次のようになります。

public class MyApiController : ApiController
{

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

私のWebAPIプロジェクトには、これらのインターフェイスの実装も含まれています。

Web APIプロジェクトはMVCプロジェクトと同じようにモデルバインディングを使用すると想定したため、すべてのIApiObjectにバインダーを提供する継承対応のModelBinderProviderと、Unityコンテナーを使用して実装へのインターフェイスを解決するカスタムモデルバインダーを作成しました。

しかし、さらに調査した結果、Web APIがパラメーターのバインドを行う方法に出会い、WebAPIが複合型のモデルバインダーではなくフォーマッターを使用していることがわかりました。リンクされたブログ投稿では、アクションパラメーターにModelBinderAttributeを使用することを推奨していますが、その属性はパラメーターとして型のみを受け入れます。ただし、私のカスタムモデルバインダーには空のコンストラクターが含まれていないため(Unityコンテナーが必要)、そのインスタンスを渡す必要があります。

私が考えることができるもう1つの方法は、フォーマッターに依存性注入を使用することです。残念ながら、これまで使ったことがないのでなじみがありません。

どちらが正しい方法ですか?そして、どうすればいいですか?

4

2 に答える 2

5

これは私が今思いついたものであり、それは機能します。

ユニティコールを実行し、解決されたタイプを使用して以降のすべての操作を別のフォーマッターに転送するカスタムフォーマッターを作成することにしました。多くのコードのように見えますが、それは、型を常に解決できるように、すべてのメソッドを上書きする必要があるためです。

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);
    }
}

最後に、カスタムフォーマッターをアプリケーション構成(Global.asax Application_Start)に登録します。現在のすべてのフォーマッターをカスタムフォーマッターのインスタンスに置き換えることを選択したので、すべてのデータ型のリフレクションを取得します。

// 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));
}
于 2012-12-19T14:49:55.913 に答える
2

サービススタック http://www.servicestack.net/をご覧になることをお勧めします

asp.net-WebApiと同じデザインになっていますが、IOCなどの機能が組み込まれています。

http://pluralsight.com/training/Courses/TableOfContents/service-stackには、サービススタックに関するすばらしいシリーズがあります。

于 2012-12-19T10:47:12.540 に答える