Reputation: 18675
I use this contract resolver for dependency-injection with Autofac
and Json.NET
:
public class AutofacContractResolver : DefaultContractResolver
{
private readonly IComponentContext _container;
public AutofacContractResolver(IComponentContext context)
{
_container = context ?? throw new ArgumentNullException(nameof(context));
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
// use Autofac to create types that have been registered with it
if (_container.IsRegistered(objectType))
{
contract.DefaultCreator = () => _container.Resolve(objectType);
}
return contract;
}
}
Then, I use it with DI to initialize the JsonSerializer
:
var contractResolver = ctx.Resolve<IContractResolver>(); // ctx = Autofac's IComponentContext
var jsonSerializer = new JsonSerializer
{
ContractResolver = contractResolver, // <-- AutofacContractResolver
};
What would be the equivalent of this technique with the new System.Text.Json in net-core-3.0
- if there is any already? I wasn't able to figure this out and couldn't find any interfaces that would look similar to this ones.
Upvotes: 4
Views: 2883
Reputation: 636
Please try this library I wrote as an extension to System.Text.Json to offer missing features: https://github.com/dahomey-technologies/Dahomey.Json.
You will find support for programmatic object mapping.
Define your own implementation of IObjectMappingConvention:
public class AutofacObjectMappingConvention : IObjectMappingConvention
{
private readonly IComponentContext _container;
public AutofacObjectMappingConvention(IComponentContext context)
{
_container = context ?? throw new ArgumentNullException(nameof(context));
}
public void Apply<T>(JsonSerializerOptions options, ObjectMapping<T> objectMapping) where T : class
{
defaultObjectMappingConvention.Apply<T>(options, objectMapping);
// use Autofac to create types that have been registered with it
if (_container.IsRegistered(objectType))
{
objectMapping.MapCreator(o => _container.Resolve<T>());
}
}
}
Implement IObjectMappingConventionProvider to associate more than one type to the convention:
public class AutofacObjectMappingConventionProvider : IObjectMappingConventionProvider
{
public IObjectMappingConvention GetConvention(Type type)
{
// here you could filter which type should be instantiated by autofac and return null for other types
return new AutofacObjectMappingConvention();
}
}
Setup json extensions by calling on JsonSerializerOptions the extension method SetupExtensions defined in the namespace Dahomey.Json:
JsonSerializerOptions options = new JsonSerializerOptions();
options.SetupExtensions();
Register the new object mapping convention for the class:
options.GetObjectMappingConventionRegistry().RegisterProvider(new AutofacObjectMappingConventionProvider());
Then serialize your class with the regular Sytem.Text.Json API:
string json = JsonSerializer.Serialize(myClass, options);
Upvotes: 1