In my project I register many ISerializers implementations with the assembly scanner. FWIW this is the code that registers my ISerializers
Scan(scanner =>
{
scanner.AssemblyContainingType<ISerializer>();
scanner.AddAllTypesOf<ISerializer>().NameBy(type => type.Name);
scanner.WithDefaultConventions();
});
Which then correctly registers
ISerializer (...ISerializer)
Scoped as: Transient
JsonSerializer Configured Instance of ...JsonSerializer
BsonSerializer Configured Instance of ...BsonSerializer
And so forth.
Currently the only way I’ve been able to figure out how to resolve the serializer I want is to hardcode a service location call with
jsonSerializer = ObjectFactory.GetNamedInstance<ISerializer>("JsonSerializer");
Now I know in my class that I specifically want the jsonSerializer so is there a way to configure a rule or similar that says for ISerializer’s to connect the named instance based on the property name? So that I could have
MySomeClass(ISerializer jsonSerializer, ....)
And StructureMap correctly resolve this scenario? Or am I approaching this wrong and perhaps I should just register the concrete type that implements ISerializer and then just specifically use
MySomeClass(JsonSerializer jsonSerializer, ....)
for something along these lines with the concrete class?
When you’re doing Dependency Injection and need to be able to create specially-typed instances of a given interface, the recommended solution is to create specialized factory classes. This allows you to use a named argument without actually injecting the container.
Example
This is the abstract type that you’ll be injecting:
Here is the concrete type, which makes use of your container (StructureMap):
Then your class would look like the following:
I’ve written this passing “Json” instead of “JsonSerializer” which won’t automatically work. But I think you should change your registration names to eliminate the redundant “Serializer” suffix (we already know it’s a serializer because we’re asking for an
ISerializer). In other words create a method like this:And register it like this:
Then you can just use the string “Json” to create it instead of “JsonSerializer”, which will look a little less ugly and feel less coupled.
If you don’t like the hard-coded strings, then another thing you can do is create an enumeration for your factory:
So instead of writing this:
You get to write this instead:
Which is going to be less error-prone in the long run.
This will probably be more maintainable in the long run because if you start changing the class names of your serializers and/or the names are inconsistent, then you can replace the simple
ToString()with aswitchstatement and actually map the enum values to the class names you’re registering.I’d probably put all of this code – including the auto-registration code in your question – in the same namespace, or even the same code file, to clearly indicate that these pieces are all interdependent.