我试图用C#创建一种ServiceManager。
我希望它有一个set和get函数。
设置签名如下所示:
public void set(string key, ServiceProvider service)
public ServiceProvider get(string key)
我不确定如何写class ServiceProvider
我希望它包含一个返回自己的create
方法
例如:
public class SomeService : ServiceProvider
{
public static SomeService create(ServiceManager serviceManager)
{
return new SomeService();
}
}
另一个例子:
public class SomeOtherService : ServiceProvider
{
protected FooService fooService;
public SomeOtherService(FooService fooService)
{
this.fooService = fooService;
}
public static SomeOtherService create(ServiceManager serviceManager)
{
return new SomeOtherService (serviceManager.get("FooService"));
}
}
如何实施ServiceProvider
强迫我编写创建方法?
EDIT1: 我想解释为什么我需要以这种方式构建它。 我的想法是使get方法 lazy ,所以当我通过它的名称调用它时,我才启动实例并将其保存为ServiceManager中的单例。
EDIT2:
这背后的想法是每个实现/继承自ServiceProvider
的类都可以按照自己的意愿实现创建。
例如:
PlayerService
需要在其构造函数中包含数据库适配器。
UtilService
在其构造函数中没有参数。
在幕后......
调用ServiceManager.get(key)
时,它会检查实例的字典,如果它不存在,则使用create()
方法创建它并将其分配给字典并返回它
最终解决方案:
namespace Infrastructure.Base.Service
{
public class ServiceManager : Contracts.IServiceManager
{
Dictionary<Type, Contracts.IServiceProvider> dictonary;
public ServiceManager()
{
dictonary = new Dictionary<Type, Contracts.IServiceProvider>();
}
public Contracts.IServiceProvider get<T>() where T : Contracts.IServiceProvider
{
if (!dictonary.ContainsKey(typeof(T)))
{
var service = (T)Activator.CreateInstance(typeof(T), this);
dictonary[typeof(T)] = service;
}
return dictonary[typeof(T)];
}
}
}
namespace Infrastructure.Base.Service.Contracts
{
public interface IServiceProvider
{
}
}
namespace Infrastructure.Base.Service.Contracts
{
public interface IServiceManager
{
Infrastructure.Base.Service.Contracts.IServiceProvider get<T>() where T : Infrastructure.Base.Service.Contracts.IServiceProvider;
}
}
USAGE:
public class PlayerService : IServiceProvider
{
PlayerAdapter playerAdapter;
public PlayerService(ServiceManager serviceManager)
{
playerAdapter = serviceManager.get<PlayerAdapter>() as PlayerAdapter;
Debug.Log("I am player service!");
}
}
public class PlayerAdapter : IServiceProvider
{
public PlayerAdapter(ServiceManager serviceManager)
{
Debug.Log(" I am PlayerAdapter!");
}
}
void Main()
{
serviceManager = new ServiceManager();
PlayerService playerService = serviceManager.get<PlayerService>() as PlayerService;
}
答案 0 :(得分:3)
您可以为基类执行类似的操作
public abstract class ServiceProvider<T> where T : new()
{
public static T Create()
{
return new T();
}
}
然后你甚至不需要在派生类中实现Create
public class SomeService : ServiceProvider<SomeService>
{
}
答案 1 :(得分:2)
您无法在C#中覆盖静态方法。静态和虚拟是该语言中的独有术语。
您似乎需要的是一个简单的存储库:
public abstract class ServiceProvider
{
}
public class ServiceManager
{
private readonly Dictionary<Type, ServiceProvider> repository;
public ServiceManager()
{
repository = new Dictionary<Type, ServiceProvider>();
}
public ServiceProvider Get<T>() where T : ServiceProvider
{
if (repository.ContainsKey(typeof(T)))
return repository[typeof(T)];
var service = (T)Activator.CreateInstance<T>();
repository[typeof(T)] = service;
return service;
}
}
现在实施具体的服务提供商:
public class MyServiceFoo : ServiceProvider
{
public MyServiceFoo()
{ /*construction logic (your Create()) goes here*/ }
}
public class MyServiceBlah : ServiceProvider
{
public MyServiceBlah()
{ /*construction logic (your Create()) goes here*/ }
}
并像这样使用它:
var manager = new ServiceManager();
var myFooProvider = manager.Get<MyServiceFoo>();
var myOtherFooProvider = manager.Get<MyServiceFoo>();
var areTheSame = ReferenceEquals(myFooProvider, myOtherFooProvider); //returns true
<强>更新强>
如果某些服务提供商在创建时需要参数,那么只需将Get
方法更改为以下内容:
public ServiceProvider Get<T>(params object[] args) where T : ServiceProvider
{
if (repository.ContainsKey(typeof(T)))
return repository[typeof(T)];
var service = (T)Activator.CreateInstance(typeof(T), args);
repository[typeof(T)] = service;
return service;
}
现在,考虑到您有以下服务:
public class MyServiceBar : ServiceProvider
{
public MyServiceBar(int myInt)
{ /*construction logic (your Create()) goes here*/ }
}
您只需:
var manager = new ServiceManager();
var myFooProvider = manager.Get<MyServiceFoo>();
var myServiceBar= manager.Get<MyServiceBar>(1);
答案 2 :(得分:0)
据我所知,现在有办法强制实现静态方法。你必须自己照顾这个。 另一种方法是你使你的类通用,在这个类中你有静态创建方法来创建派生对象:
public class ServiceProvider<T>
{
public static T Create()
{
return (T)Activator.CreateInstance(typeof(T));
}
}
答案 3 :(得分:0)
您出现的问题在软件开发中很常见,但您尝试实施的解决方案并非最佳做法。
我建议像Unity一样使用 IOC (控制容器的反转)。
使用它,您几乎可以配置有关对象生命周期的所有内容(例如,您可以指定是否需要新对象或使用单个实例,等等。)
如果某人(Unity)为您执行此操作,则不应编写代码。
不要遵循涉及反思的解决方案:在我看来,反思是问题的最后解决方案;它在运行时发生,因此您可能会对运行时错误感到惊讶,它不是轻量级操作,并且会损失每个编译时间的好处。
不要使用singleton :它是一个反模式,因为它混淆了2个响应(对象创建和对象生命周期管理)并引入了测试问题。
使用IOC,您可以管理对象的生命周期(如果您想要单个实例,则可以在需要时创建它),并且可以获得可测试性。