Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow extending genericInterfaceImplementations of DefaultObjectFactory #982

Closed
n9 opened this issue Sep 25, 2024 · 3 comments · Fixed by #985
Closed

Allow extending genericInterfaceImplementations of DefaultObjectFactory #982

n9 opened this issue Sep 25, 2024 · 3 comments · Fixed by #985

Comments

@n9
Copy link

n9 commented Sep 25, 2024

Is your feature request related to a problem? Please describe.

It seems to me that there is currently no way to extend defaultGenericInterfaceImplementations of DefaultObjectFactory.

private readonly Dictionary<Type, Type> defaultGenericInterfaceImplementations = new()
{
{ typeof(IEnumerable<>), typeof(List<>) },
{ typeof(ICollection<>), typeof(List<>) },
{ typeof(IList<>), typeof(List<>) },
{ typeof(IDictionary<,>), typeof(Dictionary<,>) }
};

Mappings are only added to defaultNonGenericInterfaceImplementations.

foreach (var pair in mappings)
{
if (!pair.Key.IsAssignableFrom(pair.Value))
{
throw new InvalidOperationException($"Type '{pair.Value}' does not implement type '{pair.Key}'.");
}
defaultNonGenericInterfaceImplementations.Add(pair.Key, pair.Value);
}

Describe the solution you'd like

Provide a "simple" way to extend defaultGenericInterfaceImplementations.

Describe alternatives you've considered

Modify copy of DefaultObjectFactory.

Additional context

N/A

@n9 n9 changed the title Allow to specify genericInterfaceImplementations for DefaultObjectFactory Allow extending genericInterfaceImplementations of DefaultObjectFactory Sep 25, 2024
@EdwardCooke
Copy link
Collaborator

How are you wanting to extend that class? If you're wanting to add additional types you can do that by passing in a dictionary of type mappings. That linked method is just making sure the types are assignable and making a copy of the passed in dictionary. We could remove the sealed part of the class so you could extend it, that wouldn't be hard at all.

@n9
Copy link
Author

n9 commented Sep 26, 2024

Yes, that will be sufficient.

Moreover, I realized that in my case extending defaultGenericInterfaceImplementations does not help, I need to create an INodeTypeResolver (as suggested here #236 (comment)).

But for mapping-like collections, I also need to tweak the serialization (mentioned here #236 (comment)). Currently, I do the following:

static readonly IObjectFactory objectFactoryForSerialization = new CustomObjectFactoryForSerialization();

...

.WithObjectGraphTraversalStrategyFactory((typeInspector, typeResolver, typeConverters, maximumRecursion) =>
    new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, CamelCaseNamingConvention.Instance, objectFactoryForSerialization))

Where CustomObjectFactoryForSerialization is this:

public class CustomObjectFactoryForSerialization : ObjectFactoryBase
{
    public override bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments)
    {
        genericArguments = descriptor.Type.GetInterfaceGenericArguments(typeof(IReadOnlyDictionary<,>));
        if (genericArguments != null)
        {
            dictionary = (IDictionary)Activator.CreateInstance(typeof(ReadOnlyDictionaryAdapter<,>).MakeGenericType(genericArguments), descriptor.Value)!;
            return true;
        }
        return base.GetDictionary(descriptor, out dictionary, out genericArguments);
    }

    public override object Create(Type type) => throw new NotSupportedException();
}

Since I cannot currently derive from DefaultObjectFactory.

Removing sealed from DefaultObjectFactory will also help in this case, I would be able to derive from DefaultObjectFactory instead of ObjectFactoryBase.

@EdwardCooke
Copy link
Collaborator

Sounds good, it'll be done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants