2013-01-19 71 views
0

我有一堂課,我想裝飾兩次。然而,當我解決這個類時,溫莎只裝飾一次,而不是使用我的2個裝飾器。我不確定爲什麼會出現這種情況,因爲我在我正在解決的課程之前註冊了兩個裝飾器,這是我理解裝飾器與Windsor一起工作的方式。爲什麼溫莎不解決我註冊的每個裝飾工?

這是我的代碼。

public interface IQueryExecuter 
{ 
    TReturn Execute<TReturn>(IQuery<TReturn> query); 
} 

public class QueryLoggingDecorator : IQueryExecuter 
{ 
    private ILogger _logger = NullLogger.Instance; 

    public ILogger Logger 
    { 
     set { _logger = value; } 
    } 

    public TReturn Execute<TReturn>(IQuery<TReturn> query) 
    { 
     _logger.Info("Before query execute"); 
     var queryResults = query.Execute(); 
     _logger.Info("After query execute"); 

     return queryResults; 
    } 
} 

public class QueryTransactionDecorator : IQueryExecuter 
{ 
    public TReturn Execute<TReturn>(IQuery<TReturn> query) 
    { 
     try 
     { 
      Console.WriteLine("Beginning transaction"); 
      var queryResults = query.Execute(); 
      Console.WriteLine("Comitting transaction"); 

      return queryResults; 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Rolling back transaction"); 
      throw; 
     } 
    } 
} 

public interface IQuery<out TReturn> 
{ 
    TReturn Execute(); 
} 

public class Query : IQuery<string> 
{ 
    public string Execute() 
    { 
     Console.WriteLine("Executing query"); 

     var queryResults = Path.GetRandomFileName(); 

     return queryResults; 
    } 
} 

這裏是我的溫莎註冊碼。

public class DefaultInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Component 
      .For<IQueryExecuter>() 
      .ImplementedBy<QueryLoggingDecorator>() 
      .LifestyleTransient()); 
     container.Register(Component 
      .For<IQueryExecuter>() 
      .ImplementedBy<QueryTransactionDecorator>() 
      .LifestyleTransient()); 
     container.Register(Component 
      .For<IQueryExecuter>() 
      .ImplementedBy<QueryExecuter>() 
      .LifestyleTransient()); 
    } 
} 

最後,這裏是我的調用代碼。

var container = new WindsorContainer(); 

container.Install(FromAssembly.This()); 

var queryExecuter = container.Resolve<IQueryExecuter>(); 
var queryResults = queryExecuter.Execute(new Query()); 

我錯過了什麼?

我認爲,當我決定IQueryExecuter溫莎將用QueryLoggingDecorator然後QueryTransactionDecorator裝飾。

回答

5

問題是這些不是裝飾者;它們只是同一接口的不同實現。裝飾者需要實際裝飾的東西,這是他們正在實施的相同接口的一個實例,因此他們可以調用鏈中的下一個裝飾器。

您需要設置一個IQueryExecuter的可注入引用。之後,溫莎處理剩下的事情,按註冊順序注入裝飾鏈(至少根據文檔)。

例如:

public class QueryLoggingDecorator : IQueryExecuter 
{ 
    private ILogger _logger = NullLogger.Instance; 
    private IQueryExecuter innerExecuter; 

    public QueryLoggingDecorator(IQueryExecuter innerExecuter) 
    { 
     this.innerExecuter = innerExecuter; 
    } 


    public ILogger Logger 
    { 
     set { _logger = value; } 
    } 

    public TReturn Execute<TReturn>(IQuery<TReturn> query) 
    { 
     _logger.Info("Before query execute"); 
     var queryResults = innerExecuter.Execute(query); 
     _logger.Info("After query execute"); 

     return queryResults; 
    } 
} 

我會承認不直接嘗試了這一點,但this blog表示,它會工作。