目标:
迭代以下集合
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()
};因为泛型参数不再是输出安全的。
问题:
有什么办法可以完成我的方案吗?
发布于 2015-07-23 21:53:26
通过将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事件中的正常模式)。
https://stackoverflow.com/questions/31598127
复制相似问题