使用 .Net 框架 4.8。
我正在為我的 MDI WinForms 應用程式創建一個快捷方式系統,因此您可以使用自定義屬性在某些表單上按下某些鍵時呼叫方法。
對于背景關系,屬性如下所示,并將它們保存為 Shortcutentry:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class ShortcutMethodAttribute : Attribute
{
public Keys[] Combination {get; set;}
public ShortcutMethodAttribute(params Keys[] combination)
{
Combination = combination;
}
}
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class)]
public sealed class ShortcutTypeAttribute : Attribute
{
}
public class ShortcutEntry
{
public ShortcutMethodAttribute Attribute { get; private set; }
public object Object { get; set; }
public Keys[] KeyCombination { get; set; }
public MethodInfo MethodInfo { get; private set; }
public ShortcutEntry(object @object, Keys[] keyCombination, MethodInfo methodInfo, ShortcutMethodAttribute attrib)
{
this.Object = @object;
this.KeyCombination = keyCombination;
this.MethodInfo = methodInfo;
this.Attribute = attrib;
}
public void Trigger()
{
MethodInfo.Invoke(Object, null);
}
}
我像這樣決議所有快捷方式并將它們保存為 Dictionary<Type, ShortcutEntry>:
public Dictionary<Type, List<ShortcutEntry>> RegisterAllAssemblyShortcuts()
{
var shortcuts = new Dictionary<Type, ShortcutEntry>();
var types = Assembly.GetExecutingAssembly().GetTypes();
var typesWithAttribute = types.Where(x => x.GetCustomAttributes<ShortcutTypeAttribute>(false).Any());
foreach (var type in typesWithAttribute)
{
var methods = type.GetMethods().Where(x => x.GetCustomAttributes(typeof(ShortcutMethodAttribute), false).Length > 0);
foreach (var method in methods)
{
var attributes = method.GetCustomAttributes(typeof(ShortcutMethodAttribute), false).OfType<ShortcutMethodAttribute>();
if (attributes == null) continue;
foreach (var attribute in attributes)
{
var se = new ShortcutEntry(
null,
attribute.KeyCombination,
method,
attribute
);
if (!shortcuts.ContainsKey(type)) shortcuts.Add(type, new List<ShortcutEntry>);
shortcuts[type].Add(se);
}
}
}
return shortcuts;
}
要使用它,您需要將 ShortcutTypeAttribute 分配給一個型別,然后將 ShortcutMethodAttribute 分配給您要呼叫的方法,并將組合鍵作為引數傳遞。
[ShortcutTypeAttribute]
public class SomeClass
{
public void SomeMethodA()
{
// do something
}
[ShortcutMethodAttribute(Keys.O, keys.I)]
public void SomeMethodB()
{
// do something
}
}
總而言之,它的作業原理是這樣的:
- 將 ShortcutTypeAttribute 添加到包含您要呼叫的方法的型別。
- 將 ShortcutMethodAttribute 添加到要呼叫的方法中(使用組合鍵)。
- 呼叫 RegisterAllAssemblyShortcuts()
- 確定活動 MDI 表單的型別。
- 監聽鍵盤輸入并檢查shortcuts[mdiType] 是否匹配。
- 如果存在 ShortcutEntry,則分配物件并呼叫 ShortcutEntry.Trigger()。
所有這些步驟都可以正常作業
當我嘗試使用在泛型型別上宣告的 ShortcutEntry.Trigger() 呼叫非泛型方法時,就會出現問題,如下所示:
[ShortcutTypeAttribute]
public class KeyboundForm<T> : Form where T : class
{
[ShortcutMethodAttribute(Keys.O)]
public virtual void KeyOPressed() {}
}
我得到的例外是:
System.InvalidOperationException:“不能對 ContainsGenericParameters 為真的型別或方法執行后期系結操作。”
我不知道為什么MethodInfofor KeyOPressed()有MethodInfo.ContainsGenericParameters = true,當:
MethodInfo.IsGenericMethod = falseMethodInfo.IsGenericMethodDefinition = false
所以我不能呼叫MakeGenericMethod()KeyOPressed 的MethodInfo
如何在泛型型別中呼叫非泛型方法?
答案編輯:現在它正在作業
當它是通用的時,替換了觸發函式以重新計算方法資訊。
public void Trigger()
{
if (MethodInfo.ContainsGenericParameters)
{
var type = Object.GetType();
var methodinfo = type.GetMethod(MethodInfo.Name);
methodinfo.Invoke(Object, null);
}
else
{
MethodInfo.Invoke(Object, null);
}
}
uj5u.com熱心網友回復:
我不知道為什么
MethodInfoforKeyOPressed() hasMethodInfo.ContainsGenericParameters == true`, 當...
這是因為KeyOPressed在泛型型別中宣告。您需要創建系結的泛型型別(即KeyboundForm<SomeActualForm>)才能呼叫它。
一種方法是更改??您的反射以僅支持系結的泛型型別:
var typesWithAttribute = types
.Where(t => !t.ContainsGenericParameters)
.Where(x => x.GetCustomAttributes<ShortcutTypeAttribute>(false).Any())
它將捕獲非泛型型別,SomeClass并系結泛型型別,如SomeOtherClass : KeyboundForm<SomeFormType>標有相應屬性。
或者檢查GetCustomAttributes<ShortcutTypeAttribute>(true)系結泛型型別 ( ) 的類的繼承屬性 ( Type.IsConstructedGenericType == true)。
有關的:
- 使用泛型類中定義的泛型引數呼叫非泛型方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/464404.html
