using System;
using Autofac;
using Autofac.Core;
using JSONAPI.ActionFilters;
using JSONAPI.Configuration;
using JSONAPI.Core;
using JSONAPI.Documents;
using JSONAPI.Documents.Builders;
using JSONAPI.Http;
using JSONAPI.Json;
using JSONAPI.QueryableTransformers;
namespace JSONAPI.Autofac
{
public class JsonApiAutofacModule : Module
{
private readonly IJsonApiConfiguration _jsonApiConfiguration;
internal JsonApiAutofacModule(IJsonApiConfiguration jsonApiConfiguration)
{
_jsonApiConfiguration = jsonApiConfiguration;
}
protected override void Load(ContainerBuilder builder)
{
// Register resource types
var registry = new ResourceTypeRegistry();
foreach (var resourceTypeConfiguration in _jsonApiConfiguration.ResourceTypeConfigurations)
{
var resourceTypeRegistration = resourceTypeConfiguration.BuildResourceTypeRegistration();
registry.AddRegistration(resourceTypeRegistration);
var configuration = resourceTypeConfiguration;
builder.Register(c => configuration)
.Keyed(resourceTypeRegistration.Type)
.Keyed(resourceTypeRegistration.ResourceTypeName)
.SingleInstance();
if (resourceTypeConfiguration.DocumentMaterializerType != null)
builder.RegisterType(resourceTypeConfiguration.DocumentMaterializerType);
foreach (var relationship in resourceTypeRegistration.Relationships)
{
IResourceTypeRelationshipConfiguration relationshipConfiguration;
if (resourceTypeConfiguration.RelationshipConfigurations
.TryGetValue(relationship.Property.Name, out relationshipConfiguration))
{
if (relationshipConfiguration.MaterializerType != null)
{
builder.RegisterType(relationshipConfiguration.MaterializerType);
continue;
}
}
// They didn't set an explicit materializer. See if they specified a factory for this resource type.
if (configuration.RelatedResourceMaterializerTypeFactory == null) continue;
var materializerType = configuration.RelatedResourceMaterializerTypeFactory(relationship);
builder.RegisterType(materializerType);
}
}
builder.Register(c => registry).As().SingleInstance();
builder.Register(c =>
{
var context = c.Resolve();
Func factory = resourceTypeName =>
{
var configuration = context.ResolveKeyed(resourceTypeName);
var registration = registry.GetRegistrationForResourceTypeName(resourceTypeName);
var parameters = new Parameter[] { new TypedParameter(typeof (IResourceTypeRegistration), registration) };
if (configuration.DocumentMaterializerType != null)
return (IDocumentMaterializer)context.Resolve(configuration.DocumentMaterializerType, parameters);
return context.Resolve(parameters);
};
return factory;
});
builder.Register(c =>
{
var context = c.Resolve();
Func factory = clrType =>
{
var configuration = context.ResolveKeyed(clrType);
var registration = registry.GetRegistrationForType(clrType);
var parameters = new Parameter[] { new TypedParameter(typeof(IResourceTypeRegistration), registration) };
if (configuration.DocumentMaterializerType != null)
return (IDocumentMaterializer)context.Resolve(configuration.DocumentMaterializerType, parameters);
return context.Resolve(parameters);
};
return factory;
});
builder.Register(c =>
{
var context = c.Resolve();
Func factory = (resourceTypeName, relationshipName) =>
{
var configuration = context.ResolveKeyed(resourceTypeName);
var registration = registry.GetRegistrationForResourceTypeName(resourceTypeName);
var relationship = registration.GetFieldByName(relationshipName) as ResourceTypeRelationship;
if (relationship == null)
throw JsonApiException.CreateForNotFound(
string.Format("No relationship `{0}` exists for the resource type `{1}`.", relationshipName, resourceTypeName));
var parameters = new Parameter[]
{
new TypedParameter(typeof(IResourceTypeRegistration), registration),
new TypedParameter(typeof(ResourceTypeRelationship), relationship)
};
// First, see if they have set an explicit materializer for this relationship
IResourceTypeRelationshipConfiguration relationshipConfiguration;
if (configuration.RelationshipConfigurations.TryGetValue(relationship.Property.Name,
out relationshipConfiguration) && relationshipConfiguration.MaterializerType != null)
return (IRelatedResourceDocumentMaterializer)context.Resolve(relationshipConfiguration.MaterializerType, parameters);
// They didn't set an explicit materializer. See if they specified a factory for this resource type.
if (configuration.RelatedResourceMaterializerTypeFactory != null)
{
var materializerType = configuration.RelatedResourceMaterializerTypeFactory(relationship);
return (IRelatedResourceDocumentMaterializer)context.Resolve(materializerType, parameters);
}
return context.Resolve(parameters);
};
return factory;
});
builder.RegisterType().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().InstancePerRequest();
// Serialization
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
// Queryable transforms
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
// Document building
builder.Register(c => _jsonApiConfiguration.LinkConventions).As().SingleInstance();
builder.RegisterType().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().SingleInstance();
builder.RegisterType().SingleInstance();
builder.RegisterType().As();
}
}
}