1

I have a class named DocumentRepository<T> with constructor

DocumentDbRepository(IDocumentCollectionName collectionName)

Where IDocumentCollectionName can be

CollectionNameFromClassName<T>

or

CollectionNameFromString

And I am resolving this by

container.RegisterType(typeof(IDocumentDbRepository<ClassA>), typeof(DocumentDbRepository<ClassA>))

container.RegisterType(typeof(IDocumentDbRepository<ClassB>), typeof(DocumentDbRepository<ClassB>))

So far so good.

But now I want to resolve IDocumentCollectionName to either CollectionNameFromClassName or CollectionNameFromString depending on the Generic Type.

So if I have ClassA, I want IDocumentCollectionName to resolve to CollectionNameFromClassName<ClassA>

And if i have ClassB, I want IDocumentCollectionName to resolve to CollectionNameFromString with a string parameter value

romain-aga
  • 1,441
  • 9
  • 14
nadlie
  • 43
  • 7
  • Possible duplicate of [Unity Register For One Interface Multiple Object and Tell Unity Where to Inject them](http://stackoverflow.com/questions/18665324/unity-register-for-one-interface-multiple-object-and-tell-unity-where-to-inject) – romain-aga Aug 18 '16 at 16:36

2 Answers2

0

According to this answer, this might work:

container.RegisterType<IDocumentCollectionName, CollectionNameFromClassName<ClassA>>("ForClassA");
container.RegisterType<IDocumentCollectionName, CollectionNameFromString>("ForClassB");

container.RegisterType<IDocumentDbRepository<ClassA>, DocumentDbRepository<ClassA>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassA")));
container.RegisterType<IDocumentDbRepository<ClassB>, DocumentDbRepository<ClassB>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassB")));

EDIT: If lisibility is your concern, I can propose to you, this:

First, you create a function to do something like your factory:

void RegisterDocumentDbRepository<TRepository, TCollection>(ContainerType container)
{
    container.RegisterType<IDocumentCollectionName, TCollection>(typeof(TRepository).Name);
    var constructor = new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>(typeof(TRepository).Name));
    container.RegisterType<IDocumentDbRepository<TRepository>, DocumentDbRepository<TRepository>>(constructor);
}

Then, you register your type like this:

RegisterDocumentDbRepository<ClassA, CollectionNameFromClassName<ClassA>>(container);
RegisterDocumentDbRepository<ClassB, CollectionNameFromString>(container);
Community
  • 1
  • 1
romain-aga
  • 1,441
  • 9
  • 14
  • This does work. I tried it, but I didn't like it very much. But I think using the factory method works better. Its bit easier to read.http://stackoverflow.com/a/18482602/6731559 – nadlie Aug 19 '16 at 09:57
  • And what about with this edit, does it better for you ? – romain-aga Aug 19 '16 at 10:16
0

I found my answer here Unity register generic type for non generic interface

end code looks like

container.RegisterInstance<Func<Type, IDocumentCollectionName>>(type =>
{
    if (type == typeof(ClassA))
        return
            (IDocumentCollectionName)
                container.Resolve(typeof(CollectionNameFromClassName<>).MakeGenericType(type));
    else
        return (IDocumentCollectionName)
            container.Resolve(typeof(CollectionNameFromString));

});

of course this means that I had to change my

DocumentDbRepository(IDocumentCollectionName collectionName)

to

Func<Type, IDocumentCollectionName> collectionName

and resolve it as

collectionName(typeof(T))
Community
  • 1
  • 1
nadlie
  • 43
  • 7