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

原文地址:https://www.cnblogs.com/Terrylee/p/406721.html