1

For my example I use Autofac (it's not necessary):

var r = builder.RegisterType<Helper>().As<IHelper>(); // usual using

What I'd like to do is to be able to register types somehow like:

string name1 = "Helper";

string name2 = "IHelper";

var r = builder.RegisterType<GetTypeFromName(name1)>().As<GetTypeFromName(name2)>();

Is it possible to do with reflection magic?

Steven
  • 166,672
  • 24
  • 332
  • 435
amplifier
  • 1,793
  • 1
  • 21
  • 55
  • Possible duplicate of [How do I use reflection to call a generic method?](https://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method) – thehennyy Nov 13 '18 at 19:26

3 Answers3

2

You would have to create a mechanism that would "figure out" which concrete types you want to register and how to expose them (the As part in AutoFac). Here is a sample of how you can register using System.Type so the missing part is obtaining the System.Types yourself.

// get your Type(s)
Type concreteType = typeof(Helper);
Type asType = typeof(IHelper);

// Autofac registration call
builder.RegisterType(concreteType).As(asType);

As you can see in the above code you should call the non-generic version of the RegisterType and As methods. (The generic versions really just call down to these anyways).

Igor
  • 60,821
  • 10
  • 100
  • 175
  • Hey, I even didn't think about non-generic version! Yes, I'm able to get both types, but unfortunately after resolving I get ComponentNotRegisteredException for 'asType' (IHelper). Any ideas? – amplifier Nov 13 '18 at 18:51
  • @amplifier - Does type `Helper` implement interface `IHelper`? – Igor Nov 13 '18 at 18:53
  • Yes, it does. Checked it, otherwise my "static" resolver wouldn't work – amplifier Nov 13 '18 at 19:11
1

Generally to resolve a type name you would need to provide more information than just the class name. So I guess the answer is "not exactly".

The method for mapping a string to a type is Type.GetType, which is documented here: https://learn.microsoft.com/en-us/dotnet/api/system.type.gettype?view=netframework-4.7.2

As you can see, in a vacuum we can't say that "Helper" or "IHelper" would be sufficient. You probably could get by with a namespace-qualified class name. (The reason why Helper works in the "hard-coded" syntax, of course, is that the compiler can take advantage of using statements in deciding what Helper should mean. That option doesn't work when GetType is trying to understand a string at runtime.)

If you can provide a custom resolver, maybe you can make it work exactly as you describe.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • I can get type variable for Helper and IHelper this way: _Type typeArgument = Assembly.LoadFrom(assemblyPath).GetTypes().First(t => t.Name == className);_ – amplifier Nov 13 '18 at 18:37
  • Sure, and if that suits your use case, it's fine. This means that you know what assembly the class comes from, which is a good place to start. But also beware of that `First` method, which may not do what you want if the assembly should happen to contain two classes (in different namespaces) with the same name. – Mark Adelsberger Nov 13 '18 at 18:41
1

If you're able to get te Type object for the type you want to register, you can pass it to Autofac using a different overload of the RegisterType method, like so:

var type = Assembly.LoadFrom(path).GetType(typeName);
builder.RegisterType(type);
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Great! But after resolving IHelper via __container.Resolve();_ I get ComponentNotRegisteredException for 'asType' (IHelper). – amplifier Nov 13 '18 at 18:53
  • If concrete type and interface types are different, you still have to use the `As()` method as you did before. – John Wu Nov 13 '18 at 19:04