[英]C# type of references (i,.e. "out" parameters) typeof(char &) or typeof(out char)
對於某些庫調試用途,我正在開發一個自定義屬性,該屬性應該能夠匹配現有方法。
例如以下:
[NetMethodAliasMethod("TryParse", Parameters = new Type[] { typeof(string), typeof(char)})]
...應該匹配 static bool System.Char.TryParse (string? s, out char result)
。 針對 ParameterInfo.ParameterType MethodInfo.GetParameters() 測試屬性“Parameters”以匹配參數(當然名稱也匹配)。
如果是string?
這是有效的,因為可空屬性不是類型的一部分。 但是,從MethodInfo
返回的第二個參數的類型是char&
,而typeof(char&)
是不允許的。 有沒有可能通過這種類型的方法?
我正在考慮泛型委托,但看不到任何方法,因為委托的使用要具體說明哪些方法是兼容的。 另一個想法是使用typeof(System.Char).GetMethod("TryParse")
。 但是,如果存在多個重載,這會導致同樣的麻煩,我們將不得不使用GetMethods
(帶有 's'),並再次匹配參數類型。
當然,我可以使用類型名稱的字符串檢查,但如果沒有其他方法,那應該是最后的手段。 但是既然Type(char&)
存在,我希望有辦法得到它嗎?
您可以使用MakeByRefType
方法創建這樣的類型。
但是,您在編寫屬性時實際上不能調用此方法,因為typeof(int).MakeByRefType()
類的東西不是屬性參數表達式(在本節的最底部定義)。
因此,我會 go 的解決方法是為您的屬性聲明一個附加參數,該參數編碼這些“by refs”的位置:
public bool[] ParametersAreByRef { get; set; }
然后做:
[NetMethodAliasMethod(
"TryParse",
Parameters = new Type[] { typeof(string), typeof(char)}
ParametersAreByRef = new bool[] { false, true })]
只有當您稍后檢索該屬性時,您才會使用MakeByRefType
根據ParametersAreByRef
中的值重新創建Type
。
var modifiedParameters = attribute.Parameters.Zip(
attribute.ParametersAreByRef, (t, b) => b ? t.MakeByRefType() : t
).ToArray()
如果您不喜歡每次都為所有非按引用參數的方法傳遞ParametersAreByRef
,您可以將Parameters
設置為位置參數(將其作為構造函數參數),然后您可以將ParametersAreByRef
初始化為Parameters.Select(x => false).ToArray()
默認情況下或構造函數中的類似內容。
正如 Jeroen Mostert 在評論中所建議的那樣,另一種解決方法是使用指針類型,因為它們在實際代碼中非常罕見,因此對按引用進行編碼:
Parameters = new Type[] { typeof(string), typeof(char*)}
當您檢索屬性實例時,檢查IsPointer
並使用GetElementType
:
var modifiedParameters = attribute.Parameters.Select(
x => x.IsPointer ? x.GetElementType().MakeByRefType() : x
).ToArray();
如果有支持字段,您也可以在Parameters
設置器中執行此操作。
或者,制作您自己的虛擬ByRef<T>
類型,以便可以注釋 by-ref-ness:
public abstract class ByRef<T> {}
…
Parameters = new Type[] { typeof(string), typeof(ByRef<char>)}
然后
// e.g. in the setter of Parameters
_parameters = Parameters.Select(
x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ByRef<>) ? x.GetGenericArguments()[0].MakeByRefType() : x
).ToArray();
我喜歡@JeroenMostert 評論的優雅,所以我在我的屬性中添加了一個 ByRef 抽象通用 class :
public abstract class ByRef<T> { };
並修改了Parameters屬性來解析類型
private Type[]? _parameters = null;
public Type[]? Parameters
{
get { return _parameters; }
set
{
if(value==null)
{
_parameters = null;
return;
}
for(int i=0; i<value.Length; i++)
{
Type type = value[i];
if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ByRef<>))
{
value[i] = type.GetGenericArguments()[0].MakeByRefType();
}
_parameters = value;
}
}
}
此設置器將所有 ByRef 解析為 T&
請注意,在我的例子中, Parameters
可以為空,因為我使用 null 作為參數通配符(即匹配任何類型和計數)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.