I am trying to add general support to our IoC container and I have a question.
Let's say I have the following type:
public interface IService<T> { ... }
public class Service<T> : IService<T> { ... }
and then the following code:
Type type = typeof(Service<>);
ConstructorInfo ctor = LogicToFindCtor(type);
Now that I have this, I have a generic type and a constructor that I cannot invoke, since it was obtained through a generic type containing generic arguments.
So, given that I am trying to resolve a specific type in my code, let's say IService<Employee>I can easily find through my code that I need to solve this using a specific type Service<T>, and what I need to type Employeein for T.
: , ctor, , .
Type specificType = typeof(Service<Employee>);
ConstructorInfo specificCtor = MapGenericToSpecific(ctor, specificType);
. , MetaDataToken ( - - ) , ? - , , if, , . . , , , , ?
:
using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
namespace ConsoleApplication10
{
public class ActivationAttribute : Attribute { }
public class TestClass<T1, T2>
{
public TestClass(String p1)
{
Console.Out.WriteLine("Wrong constructor");
}
[Activation]
public TestClass(T1 p1)
{
Console.Out.WriteLine("Right constructor, p1=" + p1);
}
public TestClass(T2 p2)
{
Console.Out.WriteLine("Wrong constructor");
}
public TestClass()
{
Console.Out.WriteLine("Wrong constructor");
}
public TestClass(T1 p1, T2 p2)
{
Console.Out.WriteLine("Wrong constructor");
}
public TestClass(String p1, T2 p2)
{
Console.Out.WriteLine("Wrong constructor");
}
public TestClass(String p1, Int32 p2)
{
Console.Out.WriteLine("Wrong constructor");
}
}
public class Program
{
static void Main(string[] args)
{
Type genericType = typeof(TestClass<,>);
ConstructorInfo genericCtor =
(from ctor in genericType.GetConstructors()
where ctor.IsDefined(typeof(ActivationAttribute), false)
select ctor).First();
Debug.Assert(genericCtor != null);
Type[] genericArguments = new Type[] { typeof(String), typeof(Int32) };
Type specificType = genericType.MakeGenericType(genericArguments);
ConstructorInfo specificCtor =
(from ctor in specificType.GetConstructors()
where ctor.MetadataToken == genericCtor.MetadataToken
select ctor).First();
Debug.Assert(specificCtor != null);
Debug.Assert(specificCtor != null, "No matching constructors was found");
Object instance = specificCtor.Invoke(new Object[] { "Test" });
Console.Out.Write("Press enter to exit...");
Console.In.ReadLine();
}
}
}