我试图给我们的IoC容器添加通用服务支持,并且我有一个问题。C#中通用类型构造函数的解析,IoC中使用通用服务注册
比方说,我有以下类型:
public interface IService<T> { ... }
public class Service<T> : IService<T> { ... }
,然后将下面的代码:
Type type = typeof(Service<>); // <-- notice no specific type here
ConstructorInfo ctor = LogicToFindCtor(type); // <-- picks one of the ctors
现在,在这一点,我有一个通用的类型,我不能调用构造函数,因为它是通过具有泛型参数的泛型类型获得的。
所以,因为在我的代码我试图解决一个特定的类型,说IService<Employee>
,我可以很容易地通过我的代码,我需要使用的具体类型Service<T>
解决这一发现,那我需要注入输入Employee
代替T
。
但是,我的问题是这样的:鉴于我有我想调用的ctor已经制定了通用的非特定类型,我如何找到特定类型的正确构造函数。
Type specificType = typeof(Service<Employee>);
ConstructorInfo specificCtor = MapGenericToSpecific(ctor, specificType);
编辑:我注意到,财产MetaDataToken两个构造函数(一个从非特定类型和特定类型的)具有相同的价值在这里,我可以用它来搭配?它仍然需要一个循环来找到正确的构造函数,但是用一个简单的if语句找到正确的构造函数的循环远比看看参数并尝试匹配这种方式更合适。我已经更改了下面的代码。这现在编译和运行,是否有更好的方法,甚至更少的反射,也许直接查找构造函数表中找到基于metadatatoken值的构造函数?
下面的代码:
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)
{
// This is the type I have in my IoC container
Type genericType = typeof(TestClass<,>);
// This is the constructor I locate
ConstructorInfo genericCtor =
(from ctor in genericType.GetConstructors()
where ctor.IsDefined(typeof(ActivationAttribute), false)
select ctor).First();
Debug.Assert(genericCtor != null);
// RESOLUTION STEP
// Upon resolution, two actual types are specified
Type[] genericArguments = new Type[] { typeof(String), typeof(Int32) };
// So I create the actual type from the generic one
Type specificType = genericType.MakeGenericType(genericArguments);
// Can I look up the "genericCtor.MetadataToken" property directly?
// or is this as good as it gets?
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();
}
}
}
请原谅我的无知,但是当你说“有界和无界的构造函数”时,实际上有什么区别? (我知道我可能没有使用正确的术语,而你的可能是正确的)你的意思是,我发现我的泛型类型的构造函数,当我还不知道T的实际类型(无界),与我需要为特定类型定位的构造函数相比,当我知道T的类型时?再次,请原谅我缺乏使用正确的术语,因为我不知道如何准确地描述我的意思。 – 2009-10-30 23:19:03
...和[Activation]属性上的良好通话....(打头像)不知道为什么我没有想到... – 2009-10-30 23:20:08
但是,只是为了得到这个直线,你是说如果我检查'SomeGenericType(T)'类型,我仍然不知道T的类型,与'SomeGenericType(T)'的* specific *类型相比,方法将具有相同的MetadataToken值? (例如,值不取决于T的类型?) – 2009-10-30 23:22:19