目标:
迭代以下集合
var collection = new IImportTrigger<EventArgs>[]
{
new FileSystemImportTrigger()
, new TimerImportTrigger()
};
以这种方式
foreach (var trigger in collection)
{
trigger.Import += trigger.OnImport;
}
这就是我目前所拥有的
public delegate void ImportTriggerEventHandler<in T>(object sender, T args) where T : EventArgs;
public interface IImportTrigger<out T> where T : EventArgs
{
event ImportTriggerEventHandler<T> Import;
void OnImport<T1>(object sender, T1 args) where T1 : EventArgs;
}
public class FileSystemImportTrigger : IImportTrigger<FileSystemEventArgs>
{
public event ImportTriggerEventHandler<FileSystemEventArgs> Import;
public void OnImport<T>(object sender, T args) where T : EventArgs { }
}
public class TimerImportTrigger : IImportTrigger<ElapsedEventArgs>
{
public event ImportTriggerEventHandler<ElapsedEventArgs> Import;
public void OnImport<T>(object sender, T args) where T : EventArgs { }
}
期望:
我想用一个通用参数定义IImportTrigger。
问题:
如果我将接口定义更改为以下内容(注意通用参数T不再是协变)。
public interface IImportTrigger<T> where T : EventArgs
{
event ImportTriggerEventHandler<T> Import;
void OnImport(object sender, T args);
}
因此
public class FileSystemImportTrigger : IImportTrigger<FileSystemEventArgs>
{
public event ImportTriggerEventHandler<FileSystemEventArgs> Import;
public void OnImport(object sender, FileSystemEventArgs args) { }
}
public class TimerImportTrigger : IImportTrigger<ElapsedEventArgs>
{
public event ImportTriggerEventHandler<ElapsedEventArgs> Import;
public void OnImport(object sender, ElapsedEventArgs args) { }
}
我无法为我的收藏品创建一个通用类型
var collection = new IImportTrigger<EventArgs>[]
{
new FileSystemImportTrigger()
, new TimerImportTrigger()
};
因为Generic参数不再是输出安全的。
问题:
有没有办法完成我的方案?
答案 0 :(得分:2)
通过将OnImport切换为非泛型,然后使用显式接口,然后创建另一个不具有协变性的派生接口,该接口具有OnImport的通用版本,您可以将其拉出。
internal class Program
{
private static void Main(string[] args)
{
var collection = new IImportTriggerBase<EventArgs>[]
{
new FileSystemImportTrigger()
, new TimerImportTrigger()
};
foreach (var trigger in collection)
{
trigger.Import += trigger.OnImport;
}
}
}
public delegate void ImportTriggerEventHandler<in T>(object sender, T args) where T : EventArgs;
public interface IImportTriggerBase<out T> where T : EventArgs
{
event ImportTriggerEventHandler<T> Import;
void OnImport(object sender, EventArgs args);
}
public interface IImportTrigger<T> : IImportTriggerBase<T> where T : EventArgs
{
void OnImport(object sender, T args);
}
public class FileSystemImportTrigger : IImportTrigger<FileSystemEventArgs>
{
public event ImportTriggerEventHandler<FileSystemEventArgs> Import;
public void OnImport(object sender, FileSystemEventArgs args) { }
void IImportTriggerBase<FileSystemEventArgs>.OnImport(object sender, EventArgs args)
{
OnImport(sender, (FileSystemEventArgs)args);
}
}
public class TimerImportTrigger : IImportTrigger<ElapsedEventArgs>
{
public event ImportTriggerEventHandler<ElapsedEventArgs> Import;
public void OnImport(object sender, ElapsedEventArgs args) { }
void IImportTriggerBase<ElapsedEventArgs>.OnImport(object sender, EventArgs args)
{
OnImport(sender, (ElapsedEventArgs)args);
}
}
但是,这确实为您提供了OnImport(object sender, EventArgs args)
上可见的IImportTrigger<T>
方法的额外信息。
这是为了解决你的问题,如果我要去做这个并且我假设正确你只是希望派生类能够了解Import
被解雇的事实你实际上没有需要OnImport暴露我会做
internal class Program
{
private static void Main(string[] args)
{
var collection = new IImportTrigger<EventArgs>[]
{
new FileSystemImportTrigger()
, new TimerImportTrigger()
};
}
}
public delegate void ImportTriggerEventHandler<in T>(object sender, T args) where T : EventArgs;
public interface IImportTrigger<out T> where T : EventArgs
{
event ImportTriggerEventHandler<T> Import;
}
public abstract class OnImportBase<T> : IImportTrigger<T> where T: EventArgs
{
public event ImportTriggerEventHandler<T> Import;
protected virtual void OnImport(object sender, T args)
{
var tmp = Import;
if (tmp != null)
{
tmp(this, args);
}
}
}
public class FileSystemImportTrigger : OnImportBase<FileSystemEventArgs>
{
protected override void OnImport(object sender, FileSystemEventArgs args)
{
DoSomeExtraStuffBeforeImport();
base.OnImport(sender, args);
}
private void DoSomeExtraStuffBeforeImport()
{
}
}
public class TimerImportTrigger : OnImportBase<ElapsedEventArgs>
{
protected override void OnImport(object sender, ElapsedEventArgs args)
{
base.OnImport(sender, args);
DoSomeExtraStuffAfterImport();
}
private void DoSomeExtraStuffAfterImport()
{
}
}
这取消了事件订阅,而是将其作为覆盖处理(这是.NET事件中的正常模式)。