我試圖給我們的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