2011-06-27 74 views
0

我註冊服務&提供一些IoC的工具(如StructreMap)如何使用一些提供者使用相同的服務?

public interface IProvider 
{ 
    void Load(int id); 
} 
public class Provider : IProvider 
{ 
    public void Load(int id) {...} 
} 
public interface IService 
{ 
    void Load(int id); 
} 
public class Service : IService 
{ 
    public Service(IProvider provider) { } 
    public void Load(int id) { provider.Load(id); } 
} 

現在我有另一個供應商

public class Provider2 : IProvider 
{ 
    public void Load(int id) {...} 
} 

我想註冊一個供應商(Provider2之間),並獲得實例來自IoC工具的Provider2服務。我能看到做到這一點的唯一方法是創建將從IService2繼承的Service2,最後一個將從IService繼承。現在我可以得到IService2類型的實例,它將啓動Provider2的提供者。

public interface IService2 : IService 
{ } 
public class Service2 : IService2 
{ 
    public Service2(IProvider2 provider) { } 
    public void Load(int id) { provider.Load(id); } 
} 

我的問題是:對於每個新的提供者,我需要爲服務編寫新的類,即使服務的功能應該保持不變?

+0

不應該是'public Service2(IProvider provider)'?然後你想達到什麼目的?你是否想要兩個具有相同接口的服務只有不同的實現 - >不同的提供者? – ub1k

+0

我想要2個具有相同實現但不同提供者實現的服務。它會接收提供者和其他時間Provider2。但是,我不會手動調用它。我想從IoC的服務 – theateist

+0

我看不到那個問題。 否則,您必須讓第二個Service解析IProvider。每個IoC都有一個選項可以在某些基礎上以不同方式解析界面。像'YourIoc.Resolve (someParameter)' – ub1k

回答

1

不,你不需要那樣做。

我建議你實現一個抽象工廠模式,根據運行時知道的值來選擇提供者的正確實現。

例如,請看這裏:http://alsagile.com/archive/2010/06/28/Abstract-Factory-and-IoC-Container-in-asp-net-MVC.aspx

它在MVC上下文中,但可以在其他場景中輕鬆實現。

例子:

你幾乎可以登記你的服務是這樣的(僞代碼):

x.For<IService>().Use<Service>();  
x.For<IProvider>().Use<Provider1>().Named("provider1"); 
x.For<IProvider>().Use<Provider2>().Named("provider2"); 

您需要一種方法在你的抽象工廠注入容器。你可以wrapp它例如像這樣:

public interface IProviderFactory 
{  
    object GetInstance<IProvider>();  
    object GetNamedInstance<IProvider>(string key); 
} 

和實現:

public class ProviderFactory : IProviderFactory 
{  
    private readonly Container _container  
    public ProviderFactory (Container container)  
    {   
     _container = container;  
    }  
    ... 
} 

和設置StructureMap解決依賴於你的抽象工廠這樣的:

x.For<IProviderFactory>.Use(new ProviderFactory(this)); 

然後到您的服務你應該像這樣注入提供商工廠

public class Service : IService 
{ 
    private readonly IProviderFactory _providerFactory; 

    public Service(IProviderFactory factory) 
    { 
     if (factory == null) 
      throw new ArgumentNullException("factory", "providerfactory cannot be null"); 
     _proiderFactory = factory; 
    } 

    public void Load(string providerName) 
    { 
     var provider = _providerFactory.GetNamedInstance(providerName); 
     // do some operation on provider 
    } 
} 

這應該工作。

+0

我試過類似這樣的'For ()。使用().Named(「core」); 對於()。使用().Named(「core」); ()。使用().named(「gen」);使用()。 ()「,但是當我試圖通過'var o = ObjectFactory.GetNamedInstance獲取服務時, var o2 = ObjectFactory.GetNamedInstance (「gen」);'它alwasy instanciate IProvider與Provider2兩種情況下,爲什麼? – theateist

+0

你只能註冊一次IServiceProvider映射。我發佈了一些代碼 –

相關問題