2013-02-15 29 views
1

讓我使用的代碼解釋一下我的問題,所以我有一個類:如何根據Autofac中的可選參數將類註冊爲單例?

public class ComplexEntity 
{ 
    private readonly ISomeDependency _someDependency; 
    private readonly int _optionalArg; 

    public ComplexEntity(ISomeDependency someDependency, int optionalArg) 
    { 
     _someDependency = someDependency; 
     _optionalArg = optionalArg; 
    } 
} 

和模塊:

public class FooModule : Module 
{ 
    protected override void OnMap(ContainerBuilder builder) 
    { 
     builder.RegisterType<ConcreteDependency>().As<ISomeDependency>().SingleInstance(); 
     builder.RegisterType<ComplexEntity>().AsSelf();//SingleInstance fails my test below. 
    } 
} 

所以我的問題是 - 我怎麼可以使用可選的參數(int類型的解決ComplexEntity - 實際上什麼類型都沒有關係),根據該可選參數,它將返回給我相同的實體(如果已經請求過)或創建一個新實體 - 只需看看下面的測試:

int optionalArgument = 10; 
    int anotherOptionalArgument = 11; 

    //I expect ResolveOptional returns same references for the same optional argument, 
    //thus instance1 should be equals instance2, but not equals instance3 
    var instance1 = _container.ResolveOptional<ComplexEntity>(
     new TypedParameter(optionalArgument.GetType(), optionalArgument)); 
    var instance2 = _container.ResolveOptional<ComplexEntity>(
     new TypedParameter(optionalArgument.GetType(), optionalArgument)); 

    var instance3 = _container.ResolveOptional<ComplexEntity>(
     new TypedParameter(anotherOptionalArgument.GetType(), anotherOptionalArgument)); 

    bool ref12Equals = object.ReferenceEquals(instance1, instance2); //should be true 
    bool ref13Equals = object.ReferenceEquals(instance1, instance3); //should be false 
    bool ref23Equals = object.ReferenceEquals(instance2, instance3); //should be false 
+0

我不明白你在這裏試圖達到什麼目的。它看起來像是在測試模塊中註冊測試類型。那麼爲什麼你不能根據你的測試要求進行註冊? – 2013-02-15 11:15:47

+0

@DanielHilgarth,好的,我刪除了所有的測試提及。 – Nagg 2013-02-15 11:20:50

+0

你有多少種不同的論證?他們是在你建造你的容器時知道的嗎? – nemesv 2013-02-15 19:38:45

回答

0

在autofac作用域中可以是singleton或factory(transient),而不是兩者。如果您需要更復雜的終身管理,我相信您需要爲此承擔責任並自行管理。如果我正確理解了你,你需要一個產生新實例或返回單例的範圍管理器。如果你仍然想使用DI,你可以把它放在容器中,這樣的:

private const int FactoryMode = 11; 
    private const int SingletonMode = 10; 

    public static void Main() 
    { 
     var containerBuilder = new ContainerBuilder(); 
     containerBuilder.RegisterType<ComplexTypeScope>().SingleInstance(); 
     containerBuilder.Register((c, p) => c.Resolve<ComplexTypeScope>().Get(p.TypedAs<int>())); 

     var container = containerBuilder.Build(); 
     ComplexType instance1 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), SingletonMode)); 
     ComplexType instance2 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), SingletonMode)); 
     ComplexType instance3 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), FactoryMode)); 

     Debug.Assert(ReferenceEquals(instance1, instance2)); 
     Debug.Assert(!ReferenceEquals(instance1, instance3)); 
    } 

    class ComplexType 
    { 
    } 

    class ComplexTypeScope 
    { 
     private readonly Lazy<ComplexType> complexTypeSingleTon; 

     public ComplexTypeScope() 
     { 
      complexTypeSingleTon = new Lazy<ComplexType>(() => new ComplexType()); 
     } 

     public ComplexType Get(int parameter) 
     { 
      return parameter == FactoryMode ? new ComplexType() : complexTypeSingleTon.Value; 
     } 
    } 
當然

這樣的做法容器不管理組件的生命週期,如自動處理。