由于泛型问题,我遇到了一些严重的设计问题.也许有人有一些建议.
编辑:所以,我知道这通常不会完成,但我已经完全改变了我的示例代码,因为我已经意识到原始的伪代码并没有真正解释我的问题.以下代码更接近于我正在处理的真实示例.我希望我的问题能更明确.我向前道歉它有点冗长,但根据我的经验,当你试图建立一个更复杂的结构时,通常会出现泛型问题.所以:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,首先,如果在ConnectorBuilder类中找到GetConnector方法,您将看到注释的代码行,如果取消注释则不会编译.这一行是我的问题的本质.问题可能从代码中显而易见,但我会尝试解释它,如果它不是:
我有一个需要IConnector的内部类(ChannelWatchDog).但不仅仅是IConnector,IConnector,因为除了非通用的IConnector方法之外,它还需要来自IConnectionMaintainable接口的GetServerTime方法.
为了简化连接器的构造,我希望使用Expression Builder模式(IConnectionBuilder接口)实现构建器.但是,我希望能够构建任何IConnector,而不仅仅是IConnector <IConnectionMaintainable>.因此,我不能以与限制它为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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是对IConnector的强制转换在运行时失败了.
所以这比我原先打算的要长得多.如果你已经阅读了这么远,那么你已经得到了我的谢意:)欢迎任何想法,包括重组代码.
顺便说一句,由于我自己没有找到解决方案,我在工厂中创建了不同的ConnectorBuilders(在本例中为ReliableConnectorBuilder)和不同的工厂方法.但我不太喜欢这个解决方案.
编辑:只是澄清并重申:我不能约束IConnector和ConnectionBuilder,因为这些需要支持未实现IConnectionMaintainable接口的情况.
代码接口?
GenericClass<IFoo> wrapper = new GenericClass<IFoo>(new FooImplementor());
Acceptor acceptor = new Acceptor(wrapper);
Run Code Online (Sandbox Code Playgroud)