由於泛型問題,我遇到了一些嚴重的設計問題。也許有人有一些建議。通用類型轉換
編輯:所以,我知道這通常不會完成,但我完全改變了我的示例代碼,因爲我意識到原始的僞代碼並沒有真正解釋我的問題。下面的代碼更接近我正在處理的真實例子。我希望我的問題會更清楚。我向前道歉,它有點冗長,但從我的經驗來看,當你試圖建立一個更復雜的結構時,泛型的問題通常會出現。所以:
class Program
{
static void Main(string[] args)
{
IConnector<IService> connector = ConnectorBuilderFactory.NewBuilder<IService>("someEndpoint").MakeReliable().GetConnector();
connector.Connect();
}
}
public interface IService : IConnectionMaintainable
{
void DoSomething();
}
public interface IConnectionMaintainable
{
DateTime GetServerTime();
}
public interface IConnector<T>
{
T Channel { get; }
void Connect();
void Disconnect();
}
public interface IConnectorBuilder<T>
{
IConnector<T> GetConnector();
IConnectorBuilder<T> MakeReliable();
// ...more connector-configuration methods
}
public class ChannelWatchDog<T> where T : IConnectionMaintainable
{
private IConnector<T> connector;
public ChannelWatchDog(IConnector<T> connector /*various other parameters*/)
{
this.connector = connector;
}
// ...methods that use connector's Connect, Disconnect, and GetServerTime methods
}
public class Connector<T> : IConnector<T>
{
private T channel;
public Connector(string endpoint)
{
// ...build channel
}
public T Channel
{
get { return channel; }
}
public void Connect()
{
// ...connect to server
}
public void Disconnect()
{
// ...disconnect from server
}
}
public class ConnectorBuilder<T> : IConnectorBuilder<T>
{
private string endpoint;
public ConnectorBuilder(string endpoint)
{
this.endpoint = endpoint;
}
public IConnector<T> GetConnector()
{
Connector<T> connector = new Connector<T>(endpoint);
// If reliability was requested, build the ChannelWatchDog: Following line does not compile:
// ChannelWatchDog<T> watchDog = new ChannelWatchDog<T>(connector);
return connector;
}
public IConnectorBuilder<T> MakeReliable()
{
// save various parameters required to build the ChannelWatchDog
return this;
}
}
public static class ConnectorBuilderFactory
{
public static IConnectorBuilder<T> NewBuilder<T>(string endpoint)
{
return new ConnectorBuilder<T>(endpoint);
}
}
所以,第一,如果你發現在ConnectorBuilder類的GetConnector方法,你會看到代碼的註釋行,這不,如果取消註釋編譯。這條線是我的問題的本質。這個問題可能是明顯的代碼,但我會盡量嘗試解釋的情況下,它是不是:
我有一個內部類(ChannelWatchDog),需要的IConnector。但不僅僅是IConnector,IConnector,因爲除非非通用IConnector方法外,它還需要IConnectionMaintainable接口中的GetServerTime方法。
爲了簡化連接器的構建,我希望使用表達式構建器模式(IConnectionBuilder接口)來實現構建器。但是,我希望能夠構建任何IConnector,而不僅僅是IConnector可持續發展>。因此,我不能像我爲ChannelWatchDog限制它一樣限制IConnectorBuilder中的T.由於缺少這個約束,當GetConnector被調用時,我無法構建它。將約束添加到MakeReliable方法中並沒有幫助。
所以,基本上我發佈這個問題的原因是我想做一些顯然不可能的事情。我想讓ChannelWatchDog和ConnectorBuilder類看起來像這樣:
public class ChannelWatchDog
{
private IConnector<IConnectionMaintainable> connector;
public ChannelWatchDog(IConnector<IConnectionMaintainable> connector /*various other parameters*/)
{
this.connector = connector;
}
// ...methods that use connector's Connect, Disconnect, and GetServerTime methods
}
public class ConnectorBuilder<T> : IConnectorBuilder<T>
{
private string endpoint;
public ConnectorBuilder(string endpoint)
{
this.endpoint = endpoint;
}
public IConnector<T> GetConnector()
{
Connector<T> connector = new Connector<T>(endpoint);
// If reliability was requested, build the ChannelWatchDog: Following line does not compile:
ChannelWatchDog watchDog = new ChannelWatchDog((IConnector<IConnectionMaintainable>)connector);
return connector;
}
public IConnectorBuilder<TReliable> MakeReliable<TReliable>() where TReliable : T, IConnectionMaintainable
{
// save various parameters required to build the ChannelWatchDog
return (IConnectorBuilder<TReliable>)this;
}
}
但是,對IConnector的轉換在運行時失敗。
所以這比我原本想要的要長得多。如果你已經閱讀了這麼多,那麼你已經得到了我的謝意:) 歡迎任何想法,包括重構代碼。
順便說一句,自己沒有找到解決方案,我在工廠中創建了不同的ConnectorBuilder(在這種情況下,一個ReliableConnectorBuilder)和不同的工廠方法。但我不太喜歡這個解決方案。
編輯:只是爲了澄清和重申:我不能約束IConnector或ConnectionBuilder,因爲這些需要支持IConnectionMaintainable接口未實現的情況。
什麼是不編譯的行上的編譯錯誤和......哪一行是無法在運行時強制轉換?你有兩個不同的問題(有效的2個不同的問題)張貼在這裏。哪個是哪個?你也可以嘗試用真正的問題而不僅僅是陳述來解決問題嗎? – Maslow 2010-12-14 14:30:13
@Maslow,註釋行不編譯,因爲連接器不受ChannelWatchDog的限制。我希望爲此解決方案,這是鑄造連接器<T>連接器<IConnectionMaintainable>是在運行時失敗。也就是說,第一個示例中沒有編譯的行與第二個示例中修改後的行在運行時引發異常的行相同。不,這不是兩個單獨的問題。這是一個問題,我正在提供我在運行時失敗的嘗試解決方案之一。 – joniba 2010-12-15 14:09:23