如何在工厂中重载通用 C# 方法?
How to overload generic C# methods in Factory?
我想创建类似工厂的东西,但它不是工厂模式的实现。
我有一个 IServiceFactory 接口:
public interface IServiceFactory
{
TServiceInterface CreateService<TServiceInterface>(string url);
}
我想在我的实现中创建两个不同的服务,它们实现两个不同的接口。假设我有:
public class FirstService : IFirstService {}
public class SecondService : ISecondService {}
public class ServiceFactory : IServiceFactory
{
public IFirstService CreateService<IFirstService>(string url)
{
// logic of creation
}
public ISecondService CreateService<ISecondService>(string url)
{
// Unforchantly, it's not an overloaded method
}
}
如何创建这样的SecondService
?我知道我的问题和我的代码示例很糟糕,这是一种不正确的方法,但想知道其他开发人员在这种情况下做了什么。谢谢。
解决您的问题的最简单方法可能是避免完全重载工厂方法(虽然不是很 'OO')。检查泛型类型参数,创建适当的实例,并将其转换回正确的类型:
public class ServiceFactory : IServiceFactory {
public TServiceType CreateService<TServiceType>(string url)
{
Type t = typeof(TServiceType);
if (t == typeof(IFirstService))
return (TServiceType) CreateFirstServiceInstance(url);
if (t == typeof(ISecondService))
return (TServiceType) CreateSecondServiceInstance(url);
throw new InvalidOperationException("Unsupported service type");
}
}
目前,IServiceFactory
的合约规定可以创建任何服务。但是,您的具体实现仅提供两种特定服务。因此,您没有实现接口契约。
我们如何解决这个问题?通过更改实现(以便可以创建任何服务)或通过更改合同(以便只能创建两个给定的服务)。 richzilla 的回答给出了前者的例子,这里是后者的例子:
public interface IServiceFactory
{
IFirstService CreateFirstService(string url);
ISecondService CreateSecondService(string url);
}
public class ServiceFactory : IServiceFactory
{
public IFirstService CreateFirstService(string url) { ... }
public ISecondService CreateSecondService(string url) { ... }
}
你甚至不需要泛型。额外的好处:如果第一个和第二个服务需要不同的参数,你也可以支持。
FirstService 和 SeconService 应该扩展一个通用接口(例如,它们的接口扩展一个通用接口,如 ServiceInterface,或者它们直接从一些通用接口扩展,如 ServiceInterface)
对于具体创建,您可以将所需的具体类型(或字符串...)传递给工厂的创建方法:
public interface IService {}
public interface IFirstService : IService {}
public interface ISecondService : IService {}
public class FirstService : IFirstService {}
public class SecondService : ISecondService {}
public class ServiceFactory : IServiceFactory {
public IService CreateService<IService>(Type class, string url)
{
// logic of creation
new class(url)
}
}
我想创建类似工厂的东西,但它不是工厂模式的实现。
我有一个 IServiceFactory 接口:
public interface IServiceFactory
{
TServiceInterface CreateService<TServiceInterface>(string url);
}
我想在我的实现中创建两个不同的服务,它们实现两个不同的接口。假设我有:
public class FirstService : IFirstService {}
public class SecondService : ISecondService {}
public class ServiceFactory : IServiceFactory
{
public IFirstService CreateService<IFirstService>(string url)
{
// logic of creation
}
public ISecondService CreateService<ISecondService>(string url)
{
// Unforchantly, it's not an overloaded method
}
}
如何创建这样的SecondService
?我知道我的问题和我的代码示例很糟糕,这是一种不正确的方法,但想知道其他开发人员在这种情况下做了什么。谢谢。
解决您的问题的最简单方法可能是避免完全重载工厂方法(虽然不是很 'OO')。检查泛型类型参数,创建适当的实例,并将其转换回正确的类型:
public class ServiceFactory : IServiceFactory {
public TServiceType CreateService<TServiceType>(string url)
{
Type t = typeof(TServiceType);
if (t == typeof(IFirstService))
return (TServiceType) CreateFirstServiceInstance(url);
if (t == typeof(ISecondService))
return (TServiceType) CreateSecondServiceInstance(url);
throw new InvalidOperationException("Unsupported service type");
}
}
目前,IServiceFactory
的合约规定可以创建任何服务。但是,您的具体实现仅提供两种特定服务。因此,您没有实现接口契约。
我们如何解决这个问题?通过更改实现(以便可以创建任何服务)或通过更改合同(以便只能创建两个给定的服务)。 richzilla 的回答给出了前者的例子,这里是后者的例子:
public interface IServiceFactory
{
IFirstService CreateFirstService(string url);
ISecondService CreateSecondService(string url);
}
public class ServiceFactory : IServiceFactory
{
public IFirstService CreateFirstService(string url) { ... }
public ISecondService CreateSecondService(string url) { ... }
}
你甚至不需要泛型。额外的好处:如果第一个和第二个服务需要不同的参数,你也可以支持。
FirstService 和 SeconService 应该扩展一个通用接口(例如,它们的接口扩展一个通用接口,如 ServiceInterface,或者它们直接从一些通用接口扩展,如 ServiceInterface) 对于具体创建,您可以将所需的具体类型(或字符串...)传递给工厂的创建方法:
public interface IService {}
public interface IFirstService : IService {}
public interface ISecondService : IService {}
public class FirstService : IFirstService {}
public class SecondService : ISecondService {}
public class ServiceFactory : IServiceFactory {
public IService CreateService<IService>(Type class, string url)
{
// logic of creation
new class(url)
}
}