2016-04-21 93 views
0

所以我有一個抽象工廠類的,這種想法是,在這家工廠的構造,我會從autofac所有已註冊的服務我很感興趣的IEnumerable通過在這個工廠有一個傳遞參數的方法,代碼將遍歷IEnumerable並返回匹配的服務。容易如餡餅,抽象的工廠模式。解決通用的IEnumerable的構造函數中使用Autofac

的問題是,我最近在我的接口工廠返回引入了泛型類型,我不知道怎麼寫的構造函數,因此autofac知道所有已註冊的服務仍然會返回,而忽視了基本上是泛型。

一些代碼:

我的接口:

public interface IRunnerServices<in T> 
{ 
    void Create(T entity); 
} 

接口

public class RunnerServiceA : IRunnerServices<A> 
{ 
    public void Create(A entity); 
} 

public class RunnerServiceB : IRunnerServices<B> 
{ 
    public void Create(B entity); 
} 

public class RunnerServiceC : IRunnerServices<C> 
{ 
    public void Create(C entity); 
} 

// Many, many more... 

而且我的作文根的某些實現,我註冊了這些服務,這樣

builder.RegisterType<RunnerServicesA>().As<IRunnerServices<A>>(); 
builder.RegisterType<RunnerServicesB>().As<IRunnerServices<B>>(); 
builder.RegisterType<RunnerServicesC>().As<IRunnerServices<C>>(); 

而只是讓你知道,A,B,C都來自同一個基類繼承

public class A : LetterBase 
{ } 

public class B : LetterBase 
{ } 

public class C : LetterBase 
{ } 

現在,我的抽象工廠

public class RunnerServicesFactory 
{ 
    private readonly IEnumerable<IRunnerServices<????>> _candidates; 
    public RunnerServicesFactory(IEnumerable<IRunnerServices<????>> candidates) 
    { 
     _candidates = candidates; 
    } 

    public IRunnerServices<????> Create(int discriminator) 
    { 
     return _candidates.First(c => c.Discriminator == discriminator); 
    } 
} 

問題出在什麼地方做我在構造上面提供和其他聲明在????讓autofac知道它應該通過這個通用的所有註冊服務?

我想這一點,但沒有運氣autofac通過什麼

IEnumerable<IRunnerServices<LetterBase>> 
+0

你想要的是同時使用協變和逆變,這是不可能的。你需要變相嗎? –

回答

0

爲了投你RunnerServiceA實施IRunnerService<LetterBase>你需要IRunnerService<T>協與出通用關鍵字改性劑,它不因爲您有一種方法可以接受T參數。

。淨不允許你投RunnerServiceAIRunnerService<LetterBase>您可以通過這個簡單的代碼嘗試:

var runnerService = (IRunnerServices<LetterBase>)new RunnerServiceA(); 
// Throws an InvalidCastException 

一個可能的解決辦法是讓IRunnerService<T>協這樣的:

public interface IRunnerServices<out T> 
    where T : LetterBase 
{ 
    void Create(LetterBase entity); 
} 

通過這樣做,你將能夠投RunnerServiceAIRunnerService<LetterBase>,做這樣的代碼:

IEnumerable<IRunnerServices<LetterBase>> runners = new IRunnerServices<LetterBase>[] { 
                 new RunnerServiceA(), 
                 new RunnerServiceB() 
                }; 

然後Autofac就能解決IEnumerable<IRunnerServices<LetterBase>>如果RunnerService註冊爲IRunnerServices<LetterBase>

順便問一下你在做什麼,讓我想想IIndex<TKey, T>

public class RunnerServicesFactory 
{ 
    private readonly IIndex<Char, IRunnerServices<LetterBase>> _candidates; 
    public RunnerServicesFactory(IIndex<Char, IRunnerServices<LetterBase>> candidates) 
    { 
     _candidates = candidates; 
    } 

    public IRunnerServices<LetterBase> Create(Char discriminator) 
    { 
     return _candidates[discriminator]; 
    } 
} 

和登記將是這樣的:

builder.RegisterType<RunnerServiceA>().Keyed<IRunnerServices<LetterBase>>('A'); 
builder.RegisterType<RunnerServiceB>().Keyed<IRunnerServices<LetterBase>>('B'); 
builder.RegisterType<RunnerServiceC>().Keyed<IRunnerServices<LetterBase>>('C'); 
+0

我並不完全瞭解你的covarient解決方案,你是否輸錯了什麼。你聲明IRunnerServices ,但是沒有任何輸出類型爲T. – raterus

+0

@raterus'out'修飾符僅用於允許.net將'RunnerServiceA'強制轉換爲'IRunnerService '。 –

相關問題