在温莎城堡中使用元数据注册组件



我正在为服务注册多个组件,并且我想为组件提供额外的元数据,而无需解析服务。

使用Microsoft扩展性框架,您可以为导出提供其他元数据,如下所示 MEF 元数据和元数据视图,温莎是否有类似的东西?

我目前正在尝试将我的组件包装在一个具有 2 个属性的类中,IMetadata 和 Lazy 需要时惰性会解析组件。

public class Program
{
    public static void Main(string[] args)
    {
        var container = new WindsorContainer();
        // register the wrapped object that contains the Component metadata and a lazy to resolve the component
        container.Register(
            Classes.FromThisAssembly()
            .BasedOn<IService>()
            .Configure(config =>
            {
                // create wrapper
                var wrapper = new WrappedComponent();
                wrapper.ComponentImpl = new Lazy<IService>(() => container.Resolve<IService>(config.Name));
                // add metadata to the wrapper 
                if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
                {
                    var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
                    wrapper.Metadata = metadata;
                }
                // set the component to the wrapper
                config.Instance(wrapper);
            })
            // also set service to wrapper
            .WithService.Select((impl, services) => new List<Type>() { typeof(WrappedComponent) }));
        // register the components
        container.Register(
            Classes.FromThisAssembly()
            .BasedOn<IService>().Configure(config =>
            {
                if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
                {
                    var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
                    config.Named(metadata.Name);
                }
            }));
    }
}
public class WrappedComponent
{
    public IComponentMetadata Metadata { get; set; }
    public Lazy<IService> ComponentImpl { get; set; }
}
[ComponentMetadata]
public class MyComponent : IService
{
    public void Operation()
    {
        // Do stuff
    }
}

public interface IService
{
    void Operation();
}
public class ComponentMetadataAttribute : Attribute, IComponentMetadata
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string SomeOtherMetadata { get; set; }
}
public interface IComponentMetadata
{
    string Name { get; set; }
    string Description { get; set; }
    string SomeOtherMetadata { get; set; }
}

您可以通过处理元数据和延迟加载组件对WrappedComponent类的提取来使WrappedComponent更加通用并简化注册。

WrappedComponent获取IKernel(来自温莎城堡(,并使用它来确定从中检索元数据的TComponent服务的实现类型。它还使用 IKernel 来初始化 Lazy 对象。请记住处理TComponent的发布,因为我们正在显式解决它。

public class WrappedComponent<TComponent> : IDisposable
{
    private readonly IKernel kernel;
    public WrappedComponent(IKernel kernel)
    {
        this.kernel = kernel;
        var componentType = this.kernel.GetHandler(typeof(TComponent)).ComponentModel.Implementation;
        this.Metadata = componentType.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)
                            .Cast<ComponentMetadataAttribute>().FirstOrDefault();
        this.ComponentImpl = new Lazy<TComponent>(() => this.kernel.Resolve<TComponent>());
    }
    public IComponentMetadata Metadata { get; }
    public Lazy<TComponent> ComponentImpl { get; }
    public void Dispose()
    {
        if (this.ComponentImpl.IsValueCreated)
        {
            this.kernel.ReleaseComponent(this.ComponentImpl.Value);
        }
    }
}

注册变得像...

container.Register(Component.For(typeof(WrappedComponent<>)).LifestyleTransient());
container.Register(Classes.FromThisAssembly().BasedOn<IService>().WithService.FromInterface().LifestyleTransient());

我假设了一种Transient的生活方式,但无论您使用哪种生活方式,最好在WrappedComponentIService中使用相同的生活方式。

IServiceMyComponentComponentMetadataAttributeIComponentMetadata保持不变。

最新更新