Castle IOC容器實踐之TypedFactory Facility(二)

摘要:在Castle IOC容器實踐之TypedFactory Facility(一)裏面大家都已經知道了如何去使用TypedFactory Facility,也已經體會到它的方便之處了,爲了更好的使用它,本篇我們對TypedFactory Facility的原理做一些簡單的分析。

 

主要內容

TypedFactory Facility原理分析

……

 

TypedFactory Facility中,有一個FactoryEntry類,這個類與我們平時項目開發中的實體類有一些類似,它用來記錄工廠的相關信息,包括工廠的ID,工廠的接口,創建方法和銷燬方法。這個類實現如下:

public class FactoryEntry
{
    
private String _id;

    
private Type _factoryInterface;

    
private String _creationMethod;

    
private String _destructionMethod;

    
public FactoryEntry(String id, Type factoryInterface, String creationMethod, String destructionMethod)
    
{
        
// 省略了驗證及異常處理

        _id 
= id;

        _factoryInterface 
= factoryInterface;

        _creationMethod 
= creationMethod;

        _destructionMethod 
= destructionMethod;
    }


    
public String Id
    
{
        
get return _id; }
    }


    
public Type FactoryInterface
    
{
        
get return _factoryInterface; }
    }


    
public String CreationMethod
    
{
        
get return _creationMethod; }
    }


    
public String DestructionMethod
    
{
        
get return _destructionMethod; }
    }

}

TypedFactoryFacility同樣是繼承於AbstractFacility,關於Facility的繼承關係我在前面的文章中已經說過了。TypedFactory Facility在初始化的時候首先會獲取工廠的類型,通過SubSystem來得到:

protected override void Init()
{
    Kernel.AddComponent( 
"typed.fac.interceptor"typeof(FactoryInterceptor) );

    ITypeConverter converter 
= (ITypeConverter)

        Kernel.GetSubSystem( SubSystemConstants.ConversionManagerKey );

    AddFactories(FacilityConfig, converter);
}


protected virtual void AddFactories(IConfiguration facilityConfig, ITypeConverter converter)
{
    
if (facilityConfig != null)
    
{
        
foreach(IConfiguration config in facilityConfig.Children["factories"].Children)
        
{
            String id 
= config.Attributes["id"];
            String creation 
= config.Attributes["creation"];
            String destruction 
= config.Attributes["destruction"];

            Type factoryType 
= (Type)
                converter.PerformConversion( config.Attributes[
"interface"], typeof(Type) );

            
try
            
{
                AddTypedFactoryEntry( 

                    
new FactoryEntry(id, factoryType, creation, destruction) );
            }

            
catch(Exception ex)
            
{
                
throw new ConfigurationException("Invalid factory entry in configuration", ex);

            }

        }

    }

}

然後再創建一個FactoryEntry實例,記錄了工廠的信息,放在了ComponentModel的擴展屬性ExtendedProperties中,設置ComponentModel的生命週期爲Singleton

public void AddTypedFactoryEntry( FactoryEntry entry )
{
    ComponentModel model 
= 

        
new ComponentModel(entry.Id, entry.FactoryInterface, typeof(Empty));

    model.LifestyleType 
= LifestyleType.Singleton;

    model.ExtendedProperties[
"typed.fac.entry"= entry;

    model.Interceptors.Add( 
new InterceptorReference( typeof(FactoryInterceptor) ) );

    Kernel.AddCustomComponent( model );

}

在容器中加入一個工廠接口的攔截器FactoryInterceptor,當從容器中獲取工廠時,會被攔截器攔截,攔截器的實現如下:

[Transient]

public class FactoryInterceptor : IMethodInterceptor, IOnBehalfAware
{
    
private FactoryEntry _entry;

    
private IKernel _kernel;

    
public FactoryInterceptor(IKernel kernel)
    
{
        _kernel 
= kernel;
    }


    
public void SetInterceptedComponentModel(ComponentModel target)
    
{
        _entry 
= (FactoryEntry) target.ExtendedProperties["typed.fac.entry"];

    }


    
public object Intercept(IMethodInvocation invocation, params object[] args)
    
{
        String name 
= invocation.Method.Name;

        
if (name.Equals(_entry.CreationMethod))
        
{
            
if (args.Length == 0 || args[0== null)
            
{
                
return _kernel[ invocation.Method.ReturnType ];

            }

            
else
            
{
                
return _kernel[ (String) args[0] ];
            }

        }


        
else if (name.Equals(_entry.DestructionMethod))
        
{
            
if (args.Length == 1)
            
{
                _kernel.ReleaseComponent( args[
0] );
                
return null;
            }

        }
        

        
return invocation.Proceed(args);
    }

}

還有一點需要我們注意的是在上面實例化ComponentModel的時候用到了一個Empty類,這個類是一個空類,沒有任何實現:

public class Empty


}

在實例化ComponentModel時需要傳入的幾個參數是:

public ComponentModel(String name, Type service, Type implementation)
{
    
this.name = name;

    
this.service = service;

    
this.implementation = implementation;

    
this.lifestyleType = LifestyleType.Undefined;

}

即這裏用一個空的類型來代替實現了的類型。

 

上篇:Castle IOC容器實踐之TypedFactory Facility(一)

 

參考資料

Castle的官方網站http://www.castleproject.org

發佈了2 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章