这是我用过的解决方案:
首先,非常感谢@HimBromBeere 提供了此解决方案的基础。本质上,他发布的是答案,但这里包含的是我如何实现此架构的相关细节。
给定以下接口:
interface IContract
{
void CommonMethod();
}
interface IContract<T> : IContract where T : EventArgs
{
event EventHandler<T> CommonEvent;
}
我有一个类,其所有意图和目的声明如下:
abstract class BaseControl
{
protected void SubscribeToContract<Type>(IContract<Type> contract)
where Type : EventArgs
{
contract.ContractChanged +=
delegate(object sender, Type e)
{
// Calls this method to perform other actions:
OnContractChanged(e);
};
}
// Called when IContract<>.ContractChanged is raised:
protected virtual void OnContractChanged(EventArgs e);
}
class SpecialControl : BaseControl, IContract<SpecialEventArgs>
{
...
protected override OnContractChanged(EventArgs e)
{
base.OnContractChanged();
PerformAction(e);
}
...
void PerformAction(EventArgs e)
{
// We can also now find out if "e" is SpecialEventArgs
if (e is SpecialEventArgs)
{
...
}
...
}
...
}
其中方法SubscribeToContract<Type>() 是从BaseControl 继承的受保护成员。这允许派生类实现自己的方法,例如PerformAction(),同时抽象出不必担心处理通用接口的东西(目标)。
在我的类中有一个event,我使用以下语句来确定参数是否实现IContract,这是IContract<> 的基本接口:
if (e.Control is IContract)
{
// Gets all the IContract<> interfaces e.Control implements:
var generics = GetIContractGenerics(e.Control.GetType());
// There might be multiple IContract<> implementations
// so therefore we need to check them all, even though in
// practice there will likely only be a single instance:
foreach (var generic in generics)
{
var method = this.GetType().GetMethod(
"SubscribeToContract", (BindingFlags.Instance | BindingFlags.NonPublic));
method = method.MakeGenericMethod(generic);
var result = method.Invoke(this, new[] { e.Control });
}
}
在我的情况下,需要设置 (BindingFlags.Instance | BindingFlags.NonPublic) 才能让 GetMethod() 函数返回 SubscribeToContract<Type>() 方法。
其中方法GetIContractGenerics()是使用this StackOverflow post中描述的方法创建的:
protected static IEnumerable<Type> GetIContractGenerics(Type type)
{
return
from implementation in type.GetInterfaces()
where implementation.IsGenericType
let definition = implementation.GetGenericTypeDefinition()
where definition == typeof(IContract<>)
select implementation.GetGenericArguments().First();
}
为方便起见,这个GetIContractGenerics() 静态方法存储在BaseControl 中。
就是这样,一切正常!感谢大家的意见!