你缺少的一件事是界面中的方差聲明。接口沒有變體,除非你聲明它是:
public interface IInvoker<in TParameter, out TResult>
// ^^ ^^^
// Look! Here too!
{
TResult Invoke(TParameter parameter);
}
的in
和out
關鍵字有助於強調方差的性質。該類型相對於in
參數是相反的,並且相對於out
參數是協變的。換句話說,你可以做到這一點,假設通常Animal : Mammal : Cat
例如:
IInvoker<Mammal, Mammal> a = Whatever();
IInvoker<Cat, Mammal> b = a;
IInvoker<Mammal, Animal> c = a;
這不是特別有用的本身,但問題是,你可以使用IInvoker<Mammal, Mammal>
任何地方,你需要一個IInvoker<Cat, Mammal>
或IInvoker<Mammal, Animal>
。
你的問題還有一些重要的缺失:你想用你的一套IInvoker<,>
實現做什麼? (「我想處理一組不同的IInvoker<,>
....」)這個問題的答案會引導你到你的解決方案。你想用一些從AbstractParameter繼承的對象來調用它們嗎?如果是這樣,李解釋說,你有一些麻煩,如果你可以做你想做的,因爲沒有什麼能夠阻止這樣的:解決這一問題將是刪除接口參數
IInvoker<AbstractParameter, AbstractResult>[] invokers = { new InvokerOne(), new InvokerTwo() };
AbstractParameter[] parameters = { new ParameterOne(), new ParameterTwo() };
AbstractResult[] results = { invokers[0].Invoke(parameters[1] /* oops */), invokers[1].Invoke(parameters[0] /* oops */) };
的一種方式。讓它調用者的私人領域,要麼做一個類,對調用者與他們的參數,這樣的事情:
interface IInvokerParameterPair<out TResult>()
where TResult : AbstractResult
{
TResult InvokeTheInvoker();
}
class InvokerParameterPair<TParameter, TResult> : IInvokerParameterPair<TResult>
where TParameter : AbstractParameter
where TResult : AbstractResult
{
private IInvoker<TParameter, TResult> _invoker;
private TParameter _parameter;
public InvokerParameterPair(IInvoker<TParameter, TResult> invoker, TParameter parameter)
{
_invoker = invoker;
_parameter = parameter;
}
public TResult InvokeTheInvoker()
{
return _invoker.Invoke(_parameter);
}
}
如果,另一方面,你想這樣做,有沒有什麼一些處理做的Invoke方法,那麼你的調用者應該採取其他一些常用的接口或從其他一些公共基類繼承,像這樣:
public interface IProcessable { }
public interface IInvoker<in TParameter, out TResult> : IProcessable
{
TResult Invoke(TParameter parameter);
}
public class InvokerOne : IInvoker<Parameter1, Result1> { /* ... */ }
public class InvokerTwo : IInvoker<Parameter2, Result2> { /* ... */ }
IProcessable[] invokers = { new InvokerOne(), new InvokerTwo() };
或本:
public interface IInvoker<in TParameter, out TResult> : IProcessable
{
TResult Invoke(TParameter parameter);
}
public abstract class Processable { }
public class InvokerOne : Processable, IInvoker<Parameter1, Result1> { /* ... */ }
public class InvokerTwo : Processable, IInvoker<Parameter2, Result2> { /* ... */ }
Processable[] invokers = { new InvokerOne(), new InvokerTwo() };
是啊,這是'OtherParameter'調用,我沒有想過。當然,我會只使用「正確的」實現進行調用,所以我沒有理會它可能出錯的方式:)謝謝! – carlpett